FFmpeg
vulkan.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) Lynne
3  *
4  * This file is part of FFmpeg.
5  *
6  * FFmpeg is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * FFmpeg is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with FFmpeg; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19  */
20 
21 #include "avassert.h"
22 #include "mem.h"
23 
24 #include "vulkan.h"
26 
27 const VkComponentMapping ff_comp_identity_map = {
28  .r = VK_COMPONENT_SWIZZLE_IDENTITY,
29  .g = VK_COMPONENT_SWIZZLE_IDENTITY,
30  .b = VK_COMPONENT_SWIZZLE_IDENTITY,
31  .a = VK_COMPONENT_SWIZZLE_IDENTITY,
32 };
33 
34 /* Converts return values to strings */
35 const char *ff_vk_ret2str(VkResult res)
36 {
37 #define CASE(VAL) case VAL: return #VAL
38  switch (res) {
39  CASE(VK_SUCCESS);
40  CASE(VK_NOT_READY);
41  CASE(VK_TIMEOUT);
42  CASE(VK_EVENT_SET);
43  CASE(VK_EVENT_RESET);
44  CASE(VK_INCOMPLETE);
45  CASE(VK_ERROR_OUT_OF_HOST_MEMORY);
46  CASE(VK_ERROR_OUT_OF_DEVICE_MEMORY);
47  CASE(VK_ERROR_INITIALIZATION_FAILED);
48  CASE(VK_ERROR_DEVICE_LOST);
49  CASE(VK_ERROR_MEMORY_MAP_FAILED);
50  CASE(VK_ERROR_LAYER_NOT_PRESENT);
51  CASE(VK_ERROR_EXTENSION_NOT_PRESENT);
52  CASE(VK_ERROR_FEATURE_NOT_PRESENT);
53  CASE(VK_ERROR_INCOMPATIBLE_DRIVER);
54  CASE(VK_ERROR_TOO_MANY_OBJECTS);
55  CASE(VK_ERROR_FORMAT_NOT_SUPPORTED);
56  CASE(VK_ERROR_FRAGMENTED_POOL);
57  CASE(VK_ERROR_UNKNOWN);
58  CASE(VK_ERROR_OUT_OF_POOL_MEMORY);
59  CASE(VK_ERROR_INVALID_EXTERNAL_HANDLE);
60  CASE(VK_ERROR_FRAGMENTATION);
61  CASE(VK_ERROR_INVALID_OPAQUE_CAPTURE_ADDRESS);
62  CASE(VK_PIPELINE_COMPILE_REQUIRED);
63  CASE(VK_ERROR_SURFACE_LOST_KHR);
64  CASE(VK_ERROR_NATIVE_WINDOW_IN_USE_KHR);
65  CASE(VK_SUBOPTIMAL_KHR);
66  CASE(VK_ERROR_OUT_OF_DATE_KHR);
67  CASE(VK_ERROR_INCOMPATIBLE_DISPLAY_KHR);
68  CASE(VK_ERROR_VALIDATION_FAILED_EXT);
69  CASE(VK_ERROR_INVALID_SHADER_NV);
70  CASE(VK_ERROR_VIDEO_PICTURE_LAYOUT_NOT_SUPPORTED_KHR);
71  CASE(VK_ERROR_VIDEO_PROFILE_OPERATION_NOT_SUPPORTED_KHR);
72  CASE(VK_ERROR_VIDEO_PROFILE_FORMAT_NOT_SUPPORTED_KHR);
73  CASE(VK_ERROR_VIDEO_PROFILE_CODEC_NOT_SUPPORTED_KHR);
74  CASE(VK_ERROR_VIDEO_STD_VERSION_NOT_SUPPORTED_KHR);
75  CASE(VK_ERROR_INVALID_DRM_FORMAT_MODIFIER_PLANE_LAYOUT_EXT);
76  CASE(VK_ERROR_NOT_PERMITTED_KHR);
77  CASE(VK_ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT);
78  CASE(VK_THREAD_IDLE_KHR);
79  CASE(VK_THREAD_DONE_KHR);
80  CASE(VK_OPERATION_DEFERRED_KHR);
81  CASE(VK_OPERATION_NOT_DEFERRED_KHR);
82  default: return "Unknown error";
83  }
84 #undef CASE
85 }
86 
88 {
89  s->nb_qfs = 0;
90  for (int i = 0; i < s->hwctx->nb_qf; i++) {
91  /* Skip duplicates */
92  int skip = 0;
93  for (int j = 0; j < s->nb_qfs; j++) {
94  if (s->qfs[j] == s->hwctx->qf[i].idx) {
95  skip = 1;
96  break;
97  }
98  }
99  if (skip)
100  continue;
101 
102  s->qfs[s->nb_qfs++] = s->hwctx->qf[i].idx;
103  }
104 }
105 
107 {
108  FFVulkanFunctions *vk = &s->vkfn;
109 
110  s->hprops = (VkPhysicalDeviceExternalMemoryHostPropertiesEXT) {
111  .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_MEMORY_HOST_PROPERTIES_EXT,
112  };
113  s->optical_flow_props = (VkPhysicalDeviceOpticalFlowPropertiesNV) {
114  .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_OPTICAL_FLOW_PROPERTIES_NV,
115  .pNext = &s->hprops,
116  };
117  s->coop_matrix_props = (VkPhysicalDeviceCooperativeMatrixPropertiesKHR) {
118  .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COOPERATIVE_MATRIX_PROPERTIES_KHR,
119  .pNext = &s->optical_flow_props,
120  };
121  s->subgroup_props = (VkPhysicalDeviceSubgroupSizeControlProperties) {
122  .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_SIZE_CONTROL_PROPERTIES,
123  .pNext = &s->coop_matrix_props,
124  };
125  s->desc_buf_props = (VkPhysicalDeviceDescriptorBufferPropertiesEXT) {
126  .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_BUFFER_PROPERTIES_EXT,
127  .pNext = &s->subgroup_props,
128  };
129  s->driver_props = (VkPhysicalDeviceDriverProperties) {
130  .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES,
131  .pNext = &s->desc_buf_props,
132  };
133  s->props = (VkPhysicalDeviceProperties2) {
134  .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2,
135  .pNext = &s->driver_props,
136  };
137 
138  s->atomic_float_feats = (VkPhysicalDeviceShaderAtomicFloatFeaturesEXT) {
139  .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_ATOMIC_FLOAT_FEATURES_EXT,
140  };
141  s->feats_12 = (VkPhysicalDeviceVulkan12Features) {
142  .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES,
143  .pNext = &s->atomic_float_feats,
144  };
145  s->feats = (VkPhysicalDeviceFeatures2) {
146  .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2,
147  .pNext = &s->feats_12,
148  };
149 
150  vk->GetPhysicalDeviceProperties2(s->hwctx->phys_dev, &s->props);
151  vk->GetPhysicalDeviceMemoryProperties(s->hwctx->phys_dev, &s->mprops);
152  vk->GetPhysicalDeviceFeatures2(s->hwctx->phys_dev, &s->feats);
153 
155 
156  if (s->qf_props)
157  return 0;
158 
159  vk->GetPhysicalDeviceQueueFamilyProperties2(s->hwctx->phys_dev, &s->tot_nb_qfs, NULL);
160 
161  s->qf_props = av_calloc(s->tot_nb_qfs, sizeof(*s->qf_props));
162  if (!s->qf_props)
163  return AVERROR(ENOMEM);
164 
165  s->query_props = av_calloc(s->tot_nb_qfs, sizeof(*s->query_props));
166  if (!s->qf_props) {
167  av_freep(&s->qf_props);
168  return AVERROR(ENOMEM);
169  }
170 
171  s->video_props = av_calloc(s->tot_nb_qfs, sizeof(*s->video_props));
172  if (!s->video_props) {
173  av_freep(&s->qf_props);
174  av_freep(&s->query_props);
175  return AVERROR(ENOMEM);
176  }
177 
178  for (uint32_t i = 0; i < s->tot_nb_qfs; i++) {
179  s->query_props[i] = (VkQueueFamilyQueryResultStatusPropertiesKHR) {
180  .sType = VK_STRUCTURE_TYPE_QUEUE_FAMILY_QUERY_RESULT_STATUS_PROPERTIES_KHR,
181  };
182  s->video_props[i] = (VkQueueFamilyVideoPropertiesKHR) {
183  .sType = VK_STRUCTURE_TYPE_QUEUE_FAMILY_VIDEO_PROPERTIES_KHR,
184  .pNext = &s->query_props[i],
185  };
186  s->qf_props[i] = (VkQueueFamilyProperties2) {
187  .sType = VK_STRUCTURE_TYPE_QUEUE_FAMILY_PROPERTIES_2,
188  .pNext = &s->video_props[i],
189  };
190  }
191 
192  vk->GetPhysicalDeviceQueueFamilyProperties2(s->hwctx->phys_dev, &s->tot_nb_qfs, s->qf_props);
193 
194  if (s->extensions & FF_VK_EXT_COOP_MATRIX) {
195  vk->GetPhysicalDeviceCooperativeMatrixPropertiesKHR(s->hwctx->phys_dev,
196  &s->coop_mat_props_nb, NULL);
197 
198  if (s->coop_mat_props_nb) {
199  s->coop_mat_props = av_malloc_array(s->coop_mat_props_nb,
200  sizeof(VkCooperativeMatrixPropertiesKHR));
201  for (int i = 0; i < s->coop_mat_props_nb; i++) {
202  s->coop_mat_props[i] = (VkCooperativeMatrixPropertiesKHR) {
203  .sType = VK_STRUCTURE_TYPE_COOPERATIVE_MATRIX_PROPERTIES_KHR,
204  };
205  }
206 
207  vk->GetPhysicalDeviceCooperativeMatrixPropertiesKHR(s->hwctx->phys_dev,
208  &s->coop_mat_props_nb,
209  s->coop_mat_props);
210  }
211  }
212 
213  return 0;
214 }
215 
216 static int vk_qf_get_index(FFVulkanContext *s, VkQueueFlagBits dev_family, int *nb)
217 {
218  for (int i = 0; i < s->hwctx->nb_qf; i++) {
219  if (s->hwctx->qf[i].flags & dev_family) {
220  *nb = s->hwctx->qf[i].num;
221  return s->hwctx->qf[i].idx;
222  }
223  }
224 
225  av_assert0(0); /* Should never happen */
226 }
227 
229  VkQueueFlagBits dev_family)
230 {
231  /* Fill in queue families from context if not done yet */
232  if (!s->nb_qfs)
234 
235  return (qf->queue_family = vk_qf_get_index(s, dev_family, &qf->nb_queues));
236 }
237 
239 {
240  FFVulkanFunctions *vk = &s->vkfn;
241 
242  for (int i = 0; i < pool->pool_size; i++) {
243  FFVkExecContext *e = &pool->contexts[i];
244 
245  if (e->fence) {
246  vk->WaitForFences(s->hwctx->act_dev, 1, &e->fence, VK_TRUE, UINT64_MAX);
247  vk->DestroyFence(s->hwctx->act_dev, e->fence, s->hwctx->alloc);
248  }
250 
252 
253  av_free(e->frame_deps);
254  av_free(e->buf_deps);
256  av_free(e->layout_dst);
257  av_free(e->access_dst);
258  av_free(e->frame_update);
259  av_free(e->frame_locked);
260  av_free(e->sem_sig);
262  av_free(e->sem_wait);
263  }
264 
265  if (pool->cmd_bufs)
266  vk->FreeCommandBuffers(s->hwctx->act_dev, pool->cmd_buf_pool,
267  pool->pool_size, pool->cmd_bufs);
268  if (pool->cmd_buf_pool)
269  vk->DestroyCommandPool(s->hwctx->act_dev, pool->cmd_buf_pool, s->hwctx->alloc);
270  if (pool->query_pool)
271  vk->DestroyQueryPool(s->hwctx->act_dev, pool->query_pool, s->hwctx->alloc);
272 
273  av_free(pool->query_data);
274  av_free(pool->cmd_bufs);
275  av_free(pool->contexts);
276 }
277 
279  FFVkExecPool *pool, int nb_contexts,
280  int nb_queries, VkQueryType query_type, int query_64bit,
281  const void *query_create_pnext)
282 {
283  int err;
284  VkResult ret;
285  FFVulkanFunctions *vk = &s->vkfn;
286 
287  VkCommandPoolCreateInfo cqueue_create;
288  VkCommandBufferAllocateInfo cbuf_create;
289 
290  const VkQueryPoolVideoEncodeFeedbackCreateInfoKHR *ef = NULL;
291 
292  if (query_type == VK_QUERY_TYPE_VIDEO_ENCODE_FEEDBACK_KHR) {
293  ef = ff_vk_find_struct(query_create_pnext,
294  VK_STRUCTURE_TYPE_QUERY_POOL_VIDEO_ENCODE_FEEDBACK_CREATE_INFO_KHR);
295  if (!ef)
296  return AVERROR(EINVAL);
297  }
298 
299  /* Create command pool */
300  cqueue_create = (VkCommandPoolCreateInfo) {
301  .sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
302  .flags = VK_COMMAND_POOL_CREATE_TRANSIENT_BIT |
303  VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,
304  .queueFamilyIndex = qf->queue_family,
305  };
306  ret = vk->CreateCommandPool(s->hwctx->act_dev, &cqueue_create,
307  s->hwctx->alloc, &pool->cmd_buf_pool);
308  if (ret != VK_SUCCESS) {
309  av_log(s, AV_LOG_ERROR, "Command pool creation failure: %s\n",
310  ff_vk_ret2str(ret));
311  err = AVERROR_EXTERNAL;
312  goto fail;
313  }
314 
315  /* Allocate space for command buffers */
316  pool->cmd_bufs = av_malloc(nb_contexts*sizeof(*pool->cmd_bufs));
317  if (!pool->cmd_bufs) {
318  err = AVERROR(ENOMEM);
319  goto fail;
320  }
321 
322  /* Allocate command buffer */
323  cbuf_create = (VkCommandBufferAllocateInfo) {
324  .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
325  .level = VK_COMMAND_BUFFER_LEVEL_PRIMARY,
326  .commandPool = pool->cmd_buf_pool,
327  .commandBufferCount = nb_contexts,
328  };
329  ret = vk->AllocateCommandBuffers(s->hwctx->act_dev, &cbuf_create,
330  pool->cmd_bufs);
331  if (ret != VK_SUCCESS) {
332  av_log(s, AV_LOG_ERROR, "Command buffer alloc failure: %s\n",
333  ff_vk_ret2str(ret));
334  err = AVERROR_EXTERNAL;
335  goto fail;
336  }
337 
338  /* Query pool */
339  if (nb_queries) {
340  VkQueryPoolCreateInfo query_pool_info = {
341  .sType = VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO,
342  .pNext = query_create_pnext,
343  .queryType = query_type,
344  .queryCount = nb_queries*nb_contexts,
345  };
346  ret = vk->CreateQueryPool(s->hwctx->act_dev, &query_pool_info,
347  s->hwctx->alloc, &pool->query_pool);
348  if (ret != VK_SUCCESS) {
349  av_log(s, AV_LOG_ERROR, "Query pool alloc failure: %s\n",
350  ff_vk_ret2str(ret));
351  err = AVERROR_EXTERNAL;
352  goto fail;
353  }
354 
355  pool->nb_queries = nb_queries;
356  pool->query_status_stride = 1 + 1; /* One result, one status by default */
357  pool->query_results = nb_queries;
358  pool->query_statuses = nb_queries;
359 
360  /* Video encode quieries produce two results per query */
361  if (query_type == VK_QUERY_TYPE_VIDEO_ENCODE_FEEDBACK_KHR) {
362  int nb_results = av_popcount(ef->encodeFeedbackFlags);
363  pool->query_status_stride = nb_results + 1;
364  pool->query_results *= nb_results;
365  } else if (query_type == VK_QUERY_TYPE_RESULT_STATUS_ONLY_KHR) {
366  pool->query_status_stride = 1;
367  pool->query_results = 0;
368  }
369 
370  pool->qd_size = (pool->query_results + pool->query_statuses)*(query_64bit ? 8 : 4);
371 
372  /* Allocate space for the query data */
373  pool->query_data = av_calloc(nb_contexts, pool->qd_size);
374  if (!pool->query_data) {
375  err = AVERROR(ENOMEM);
376  goto fail;
377  }
378  }
379 
380  /* Allocate space for the contexts */
381  pool->contexts = av_calloc(nb_contexts, sizeof(*pool->contexts));
382  if (!pool->contexts) {
383  err = AVERROR(ENOMEM);
384  goto fail;
385  }
386 
387  pool->pool_size = nb_contexts;
388 
389  /* Init contexts */
390  for (int i = 0; i < pool->pool_size; i++) {
391  FFVkExecContext *e = &pool->contexts[i];
392  VkFenceCreateInfo fence_create = {
393  .sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,
394  .flags = VK_FENCE_CREATE_SIGNALED_BIT,
395  };
396 
397  /* Mutex */
398  err = pthread_mutex_init(&e->lock, NULL);
399  if (err != 0)
400  return AVERROR(err);
401 
402  /* Fence */
403  ret = vk->CreateFence(s->hwctx->act_dev, &fence_create, s->hwctx->alloc,
404  &e->fence);
405  if (ret != VK_SUCCESS) {
406  av_log(s, AV_LOG_ERROR, "Failed to create submission fence: %s\n",
407  ff_vk_ret2str(ret));
408  return AVERROR_EXTERNAL;
409  }
410 
411  e->idx = i;
412  e->parent = pool;
413 
414  /* Query data */
415  e->query_data = ((uint8_t *)pool->query_data) + pool->qd_size*i;
416  e->query_idx = nb_queries*i;
417 
418  /* Command buffer */
419  e->buf = pool->cmd_bufs[i];
420 
421  /* Queue index distribution */
422  e->qi = i % qf->nb_queues;
423  e->qf = qf->queue_family;
424  vk->GetDeviceQueue(s->hwctx->act_dev, qf->queue_family,
425  e->qi, &e->queue);
426  }
427 
428  return 0;
429 
430 fail:
431  ff_vk_exec_pool_free(s, pool);
432  return err;
433 }
434 
436  void **data, VkQueryResultFlagBits flags)
437 {
438  FFVulkanFunctions *vk = &s->vkfn;
439  const FFVkExecPool *pool = e->parent;
440  VkQueryResultFlags qf = flags & ~(VK_QUERY_RESULT_64_BIT |
441  VK_QUERY_RESULT_WITH_STATUS_BIT_KHR);
442 
443  if (!e->query_data) {
444  av_log(s, AV_LOG_ERROR, "Requested a query with a NULL query_data pointer!\n");
445  return VK_INCOMPLETE;
446  }
447 
448  qf |= pool->query_64bit ?
449  VK_QUERY_RESULT_64_BIT : 0x0;
450  qf |= pool->query_statuses ?
451  VK_QUERY_RESULT_WITH_STATUS_BIT_KHR : 0x0;
452 
453  if (data)
454  *data = e->query_data;
455 
456  return vk->GetQueryPoolResults(s->hwctx->act_dev, pool->query_pool,
457  e->query_idx,
458  pool->nb_queries,
459  pool->qd_size, e->query_data,
460  pool->qd_size, qf);
461 }
462 
464 {
465  uint32_t idx = pool->idx++;
466  idx %= pool->pool_size;
467  return &pool->contexts[idx];
468 }
469 
471 {
472  FFVulkanFunctions *vk = &s->vkfn;
474  vk->WaitForFences(s->hwctx->act_dev, 1, &e->fence, VK_TRUE, UINT64_MAX);
477 }
478 
480 {
481  VkResult ret;
482  FFVulkanFunctions *vk = &s->vkfn;
483  const FFVkExecPool *pool = e->parent;
484 
485  VkCommandBufferBeginInfo cmd_start = {
486  .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
487  .flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,
488  };
489 
490  /* Wait for the fence to be signalled */
491  vk->WaitForFences(s->hwctx->act_dev, 1, &e->fence, VK_TRUE, UINT64_MAX);
492 
493  /* vkResetFences is defined as being host-synchronized */
495  vk->ResetFences(s->hwctx->act_dev, 1, &e->fence);
497 
498  /* Discard queue dependencies */
500 
501  ret = vk->BeginCommandBuffer(e->buf, &cmd_start);
502  if (ret != VK_SUCCESS) {
503  av_log(s, AV_LOG_ERROR, "Failed to start command recoding: %s\n",
504  ff_vk_ret2str(ret));
505  return AVERROR_EXTERNAL;
506  }
507 
508  if (pool->nb_queries)
509  vk->CmdResetQueryPool(e->buf, pool->query_pool,
510  e->query_idx, pool->nb_queries);
511 
512  return 0;
513 }
514 
516 {
517  for (int j = 0; j < e->nb_buf_deps; j++)
518  av_buffer_unref(&e->buf_deps[j]);
519  e->nb_buf_deps = 0;
520 
521  for (int j = 0; j < e->nb_frame_deps; j++) {
522  AVFrame *f = e->frame_deps[j];
523  if (e->frame_locked[j]) {
524  AVHWFramesContext *hwfc = (AVHWFramesContext *)f->hw_frames_ctx->data;
525  AVVulkanFramesContext *vkfc = hwfc->hwctx;
526  AVVkFrame *vkf = (AVVkFrame *)f->data[0];
527  vkfc->unlock_frame(hwfc, vkf);
528  e->frame_locked[j] = 0;
529  }
530  e->frame_update[j] = 0;
531  if (f->buf[0])
532  av_frame_free(&e->frame_deps[j]);
533  }
534  e->nb_frame_deps = 0;
535 
536  e->sem_wait_cnt = 0;
537  e->sem_sig_cnt = 0;
538  e->sem_sig_val_dst_cnt = 0;
539 }
540 
542  AVBufferRef **deps, int nb_deps, int ref)
543 {
545  (e->nb_buf_deps + nb_deps) * sizeof(*dst));
546  if (!dst) {
548  return AVERROR(ENOMEM);
549  }
550 
551  e->buf_deps = dst;
552 
553  for (int i = 0; i < nb_deps; i++) {
554  e->buf_deps[e->nb_buf_deps] = ref ? av_buffer_ref(deps[i]) : deps[i];
555  if (!e->buf_deps[e->nb_buf_deps]) {
557  return AVERROR(ENOMEM);
558  }
559  e->nb_buf_deps++;
560  }
561 
562  return 0;
563 }
564 
565 #define ARR_REALLOC(str, arr, alloc_s, cnt) \
566  do { \
567  arr = av_fast_realloc(str->arr, alloc_s, (cnt + 1)*sizeof(*arr)); \
568  if (!arr) { \
569  ff_vk_exec_discard_deps(s, e); \
570  return AVERROR(ENOMEM); \
571  } \
572  str->arr = arr; \
573  } while (0)
574 
575 typedef struct TempSyncCtx {
576  int nb_sem;
577  VkSemaphore sem[];
578 } TempSyncCtx;
579 
580 static void destroy_tmp_semaphores(void *opaque, uint8_t *data)
581 {
582  FFVulkanContext *s = opaque;
583  FFVulkanFunctions *vk = &s->vkfn;
584  TempSyncCtx *ts = (TempSyncCtx *)data;
585 
586  for (int i = 0; i < ts->nb_sem; i++)
587  vk->DestroySemaphore(s->hwctx->act_dev, ts->sem[i], s->hwctx->alloc);
588 
589  av_free(ts);
590 }
591 
593  VkSemaphore *sem, int nb,
594  VkPipelineStageFlagBits2 stage,
595  int wait)
596 {
597  int err;
598  size_t buf_size;
599  AVBufferRef *buf;
600  TempSyncCtx *ts;
601  FFVulkanFunctions *vk = &s->vkfn;
602 
603  /* Do not transfer ownership if we're signalling a binary semaphore,
604  * since we're probably exporting it. */
605  if (!wait) {
606  for (int i = 0; i < nb; i++) {
607  VkSemaphoreSubmitInfo *sem_sig;
608  ARR_REALLOC(e, sem_sig, &e->sem_sig_alloc, e->sem_sig_cnt);
609 
610  e->sem_sig[e->sem_sig_cnt++] = (VkSemaphoreSubmitInfo) {
611  .sType = VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO,
612  .semaphore = sem[i],
613  .stageMask = stage,
614  };
615  }
616 
617  return 0;
618  }
619 
620  buf_size = sizeof(int) + sizeof(VkSemaphore)*nb;
621  ts = av_mallocz(buf_size);
622  if (!ts) {
623  err = AVERROR(ENOMEM);
624  goto fail;
625  }
626 
627  memcpy(ts->sem, sem, nb*sizeof(*sem));
628  ts->nb_sem = nb;
629 
630  buf = av_buffer_create((uint8_t *)ts, buf_size, destroy_tmp_semaphores, s, 0);
631  if (!buf) {
632  av_free(ts);
633  err = AVERROR(ENOMEM);
634  goto fail;
635  }
636 
637  err = ff_vk_exec_add_dep_buf(s, e, &buf, 1, 0);
638  if (err < 0) {
639  av_buffer_unref(&buf);
640  return err;
641  }
642 
643  for (int i = 0; i < nb; i++) {
644  VkSemaphoreSubmitInfo *sem_wait;
646 
647  e->sem_wait[e->sem_wait_cnt++] = (VkSemaphoreSubmitInfo) {
648  .sType = VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO,
649  .semaphore = sem[i],
650  .stageMask = stage,
651  };
652  }
653 
654  return 0;
655 
656 fail:
657  for (int i = 0; i < nb; i++)
658  vk->DestroySemaphore(s->hwctx->act_dev, sem[i], s->hwctx->alloc);
659 
660  return err;
661 }
662 
664  VkPipelineStageFlagBits2 wait_stage,
665  VkPipelineStageFlagBits2 signal_stage)
666 {
667  uint8_t *frame_locked;
668  uint8_t *frame_update;
669  AVFrame **frame_deps;
670  VkImageLayout *layout_dst;
671  uint32_t *queue_family_dst;
672  VkAccessFlagBits *access_dst;
673 
674  AVHWFramesContext *hwfc = (AVHWFramesContext *)f->hw_frames_ctx->data;
675  AVVulkanFramesContext *vkfc = hwfc->hwctx;
676  AVVkFrame *vkf = (AVVkFrame *)f->data[0];
677  int nb_images = ff_vk_count_images(vkf);
678 
679  /* Don't add duplicates */
680  for (int i = 0; i < e->nb_frame_deps; i++)
681  if (e->frame_deps[i]->data[0] == f->data[0])
682  return 1;
683 
684  ARR_REALLOC(e, layout_dst, &e->layout_dst_alloc, e->nb_frame_deps);
685  ARR_REALLOC(e, queue_family_dst, &e->queue_family_dst_alloc, e->nb_frame_deps);
686  ARR_REALLOC(e, access_dst, &e->access_dst_alloc, e->nb_frame_deps);
687 
688  ARR_REALLOC(e, frame_locked, &e->frame_locked_alloc_size, e->nb_frame_deps);
689  ARR_REALLOC(e, frame_update, &e->frame_update_alloc_size, e->nb_frame_deps);
690  ARR_REALLOC(e, frame_deps, &e->frame_deps_alloc_size, e->nb_frame_deps);
691 
692  e->frame_deps[e->nb_frame_deps] = f->buf[0] ? av_frame_clone(f) : f;
693  if (!e->frame_deps[e->nb_frame_deps]) {
695  return AVERROR(ENOMEM);
696  }
697 
698  vkfc->lock_frame(hwfc, vkf);
699  e->frame_locked[e->nb_frame_deps] = 1;
700  e->frame_update[e->nb_frame_deps] = 0;
701  e->nb_frame_deps++;
702 
703  for (int i = 0; i < nb_images; i++) {
704  VkSemaphoreSubmitInfo *sem_wait;
705  VkSemaphoreSubmitInfo *sem_sig;
706  uint64_t **sem_sig_val_dst;
707 
709  ARR_REALLOC(e, sem_sig, &e->sem_sig_alloc, e->sem_sig_cnt);
710  ARR_REALLOC(e, sem_sig_val_dst, &e->sem_sig_val_dst_alloc, e->sem_sig_val_dst_cnt);
711 
712  e->sem_wait[e->sem_wait_cnt++] = (VkSemaphoreSubmitInfo) {
713  .sType = VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO,
714  .semaphore = vkf->sem[i],
715  .value = vkf->sem_value[i],
716  .stageMask = wait_stage,
717  };
718 
719  e->sem_sig[e->sem_sig_cnt++] = (VkSemaphoreSubmitInfo) {
720  .sType = VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO,
721  .semaphore = vkf->sem[i],
722  .value = vkf->sem_value[i] + 1,
723  .stageMask = signal_stage,
724  };
725 
726  e->sem_sig_val_dst[e->sem_sig_val_dst_cnt] = &vkf->sem_value[i];
727  e->sem_sig_val_dst_cnt++;
728  }
729 
730  return 0;
731 }
732 
734  VkImageMemoryBarrier2 *bar, uint32_t *nb_img_bar)
735 {
736  int i;
737  for (i = 0; i < e->nb_frame_deps; i++)
738  if (e->frame_deps[i]->data[0] == f->data[0])
739  break;
740  av_assert0(i < e->nb_frame_deps);
741 
742  /* Don't update duplicates */
743  if (nb_img_bar && !e->frame_update[i])
744  (*nb_img_bar)++;
745 
746  e->queue_family_dst[i] = bar->dstQueueFamilyIndex;
747  e->access_dst[i] = bar->dstAccessMask;
748  e->layout_dst[i] = bar->newLayout;
749  e->frame_update[i] = 1;
750 }
751 
753  VkSemaphore *dst, uint64_t *dst_val,
754  AVFrame *f)
755 {
756  uint64_t **sem_sig_val_dst;
757  AVVkFrame *vkf = (AVVkFrame *)f->data[0];
758 
759  /* Reject unknown frames */
760  int i;
761  for (i = 0; i < e->nb_frame_deps; i++)
762  if (e->frame_deps[i]->data[0] == f->data[0])
763  break;
764  if (i == e->nb_frame_deps)
765  return AVERROR(EINVAL);
766 
767  ARR_REALLOC(e, sem_sig_val_dst, &e->sem_sig_val_dst_alloc, e->sem_sig_val_dst_cnt);
768 
769  *dst = vkf->sem[0];
770  *dst_val = vkf->sem_value[0];
771 
772  e->sem_sig_val_dst[e->sem_sig_val_dst_cnt] = dst_val;
773  e->sem_sig_val_dst_cnt++;
774 
775  return 0;
776 }
777 
779 {
780  VkResult ret;
781  FFVulkanFunctions *vk = &s->vkfn;
782  VkCommandBufferSubmitInfo cmd_buf_info = (VkCommandBufferSubmitInfo) {
783  .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_SUBMIT_INFO,
784  .commandBuffer = e->buf,
785  };
786  VkSubmitInfo2 submit_info = (VkSubmitInfo2) {
787  .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO_2,
788  .pCommandBufferInfos = &cmd_buf_info,
789  .commandBufferInfoCount = 1,
790  .pWaitSemaphoreInfos = e->sem_wait,
791  .waitSemaphoreInfoCount = e->sem_wait_cnt,
792  .pSignalSemaphoreInfos = e->sem_sig,
793  .signalSemaphoreInfoCount = e->sem_sig_cnt,
794  };
795 
796  ret = vk->EndCommandBuffer(e->buf);
797  if (ret != VK_SUCCESS) {
798  av_log(s, AV_LOG_ERROR, "Unable to finish command buffer: %s\n",
799  ff_vk_ret2str(ret));
801  return AVERROR_EXTERNAL;
802  }
803 
804  s->hwctx->lock_queue(s->device, e->qf, e->qi);
805  ret = vk->QueueSubmit2(e->queue, 1, &submit_info, e->fence);
806  s->hwctx->unlock_queue(s->device, e->qf, e->qi);
807 
808  if (ret != VK_SUCCESS) {
809  av_log(s, AV_LOG_ERROR, "Unable to submit command buffer: %s\n",
810  ff_vk_ret2str(ret));
812  return AVERROR_EXTERNAL;
813  }
814 
815  for (int i = 0; i < e->sem_sig_val_dst_cnt; i++)
816  *e->sem_sig_val_dst[i] += 1;
817 
818  /* Unlock all frames */
819  for (int j = 0; j < e->nb_frame_deps; j++) {
820  if (e->frame_locked[j]) {
821  AVFrame *f = e->frame_deps[j];
822  AVHWFramesContext *hwfc = (AVHWFramesContext *)f->hw_frames_ctx->data;
823  AVVulkanFramesContext *vkfc = hwfc->hwctx;
824  AVVkFrame *vkf = (AVVkFrame *)f->data[0];
825 
826  if (e->frame_update[j]) {
827  int nb_images = ff_vk_count_images(vkf);
828  for (int i = 0; i < nb_images; i++) {
829  vkf->layout[i] = e->layout_dst[j];
830  vkf->access[i] = e->access_dst[j];
831  vkf->queue_family[i] = e->queue_family_dst[j];
832  }
833  }
834  vkfc->unlock_frame(hwfc, vkf);
835  e->frame_locked[j] = 0;
836  }
837  }
838 
839  e->had_submission = 1;
840 
841  return 0;
842 }
843 
844 int ff_vk_alloc_mem(FFVulkanContext *s, VkMemoryRequirements *req,
845  VkMemoryPropertyFlagBits req_flags, void *alloc_extension,
846  VkMemoryPropertyFlagBits *mem_flags, VkDeviceMemory *mem)
847 {
848  VkResult ret;
849  int index = -1;
850  FFVulkanFunctions *vk = &s->vkfn;
851 
852  VkMemoryAllocateInfo alloc_info = {
853  .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
854  .pNext = alloc_extension,
855  };
856 
857  /* Align if we need to */
858  if ((req_flags != UINT32_MAX) && req_flags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT)
859  req->size = FFALIGN(req->size, s->props.properties.limits.minMemoryMapAlignment);
860 
861  alloc_info.allocationSize = req->size;
862 
863  /* The vulkan spec requires memory types to be sorted in the "optimal"
864  * order, so the first matching type we find will be the best/fastest one */
865  for (int i = 0; i < s->mprops.memoryTypeCount; i++) {
866  /* The memory type must be supported by the requirements (bitfield) */
867  if (!(req->memoryTypeBits & (1 << i)))
868  continue;
869 
870  /* The memory type flags must include our properties */
871  if ((req_flags != UINT32_MAX) &&
872  ((s->mprops.memoryTypes[i].propertyFlags & req_flags) != req_flags))
873  continue;
874 
875  /* Found a suitable memory type */
876  index = i;
877  break;
878  }
879 
880  if (index < 0) {
881  av_log(s, AV_LOG_ERROR, "No memory type found for flags 0x%x\n",
882  req_flags);
883  return AVERROR(EINVAL);
884  }
885 
886  alloc_info.memoryTypeIndex = index;
887 
888  ret = vk->AllocateMemory(s->hwctx->act_dev, &alloc_info,
889  s->hwctx->alloc, mem);
890  if (ret != VK_SUCCESS)
891  return AVERROR(ENOMEM);
892 
893  if (mem_flags)
894  *mem_flags |= s->mprops.memoryTypes[index].propertyFlags;
895 
896  return 0;
897 }
898 
900  void *pNext, void *alloc_pNext,
901  VkBufferUsageFlags usage, VkMemoryPropertyFlagBits flags)
902 {
903  int err;
904  VkResult ret;
905  int use_ded_mem;
906  FFVulkanFunctions *vk = &s->vkfn;
907 
908  VkBufferCreateInfo buf_spawn = {
909  .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
910  .pNext = pNext,
911  .usage = usage,
912  .sharingMode = VK_SHARING_MODE_EXCLUSIVE,
913  .size = size, /* Gets FFALIGNED during alloc if host visible
914  but should be ok */
915  };
916 
917  VkMemoryAllocateFlagsInfo alloc_flags = {
918  .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_FLAGS_INFO,
919  .flags = VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT,
920  };
921  VkBufferMemoryRequirementsInfo2 req_desc = {
922  .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_REQUIREMENTS_INFO_2,
923  };
924  VkMemoryDedicatedAllocateInfo ded_alloc = {
925  .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO,
926  .pNext = alloc_pNext,
927  };
928  VkMemoryDedicatedRequirements ded_req = {
929  .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS,
930  };
931  VkMemoryRequirements2 req = {
932  .sType = VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2,
933  .pNext = &ded_req,
934  };
935 
936  ret = vk->CreateBuffer(s->hwctx->act_dev, &buf_spawn, s->hwctx->alloc, &buf->buf);
937  if (ret != VK_SUCCESS) {
938  av_log(s, AV_LOG_ERROR, "Failed to create buffer: %s\n",
939  ff_vk_ret2str(ret));
940  return AVERROR_EXTERNAL;
941  }
942 
943  req_desc.buffer = buf->buf;
944 
945  vk->GetBufferMemoryRequirements2(s->hwctx->act_dev, &req_desc, &req);
946 
947  /* In case the implementation prefers/requires dedicated allocation */
948  use_ded_mem = ded_req.prefersDedicatedAllocation |
949  ded_req.requiresDedicatedAllocation;
950  if (use_ded_mem) {
951  ded_alloc.buffer = buf->buf;
952  ded_alloc.pNext = alloc_pNext;
953  alloc_pNext = &ded_alloc;
954  }
955 
956  if (usage & VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT) {
957  alloc_flags.pNext = alloc_pNext;
958  alloc_pNext = &alloc_flags;
959  }
960 
961  err = ff_vk_alloc_mem(s, &req.memoryRequirements, flags, alloc_pNext,
962  &buf->flags, &buf->mem);
963  if (err)
964  return err;
965 
966  ret = vk->BindBufferMemory(s->hwctx->act_dev, buf->buf, buf->mem, 0);
967  if (ret != VK_SUCCESS) {
968  av_log(s, AV_LOG_ERROR, "Failed to bind memory to buffer: %s\n",
969  ff_vk_ret2str(ret));
970  return AVERROR_EXTERNAL;
971  }
972 
973  if (usage & VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT) {
974  VkBufferDeviceAddressInfo address_info = {
975  .sType = VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO,
976  .buffer = buf->buf,
977  };
978  buf->address = vk->GetBufferDeviceAddress(s->hwctx->act_dev, &address_info);
979  }
980 
981  buf->size = size;
982 
983  return 0;
984 }
985 
986 static void destroy_avvkbuf(void *opaque, uint8_t *data)
987 {
988  FFVulkanContext *s = opaque;
989  FFVkBuffer *buf = (FFVkBuffer *)data;
990  ff_vk_free_buf(s, buf);
991  av_free(buf);
992 }
993 
995  void *pNext, void *alloc_pNext,
996  VkBufferUsageFlags usage, VkMemoryPropertyFlagBits flags)
997 {
998  int err;
999  AVBufferRef *buf;
1000  FFVkBuffer *vkb = av_mallocz(sizeof(*vkb));
1001  if (!vkb)
1002  return AVERROR(ENOMEM);
1003 
1004  err = ff_vk_create_buf(s, vkb, size, pNext, alloc_pNext, usage, flags);
1005  if (err < 0) {
1006  av_free(vkb);
1007  return err;
1008  }
1009 
1010  buf = av_buffer_create((uint8_t *)vkb, sizeof(*vkb), destroy_avvkbuf, s, 0);
1011  if (!buf) {
1012  destroy_avvkbuf(s, (uint8_t *)vkb);
1013  return AVERROR(ENOMEM);
1014  }
1015 
1016  *ref = buf;
1017 
1018  return 0;
1019 }
1020 
1021 int ff_vk_map_buffers(FFVulkanContext *s, FFVkBuffer **buf, uint8_t *mem[],
1022  int nb_buffers, int invalidate)
1023 {
1024  VkResult ret;
1025  FFVulkanFunctions *vk = &s->vkfn;
1026  VkMappedMemoryRange inval_list[64];
1027  int inval_count = 0;
1028 
1029  for (int i = 0; i < nb_buffers; i++) {
1030  void *dst;
1031  ret = vk->MapMemory(s->hwctx->act_dev, buf[i]->mem, 0,
1032  VK_WHOLE_SIZE, 0, &dst);
1033  if (ret != VK_SUCCESS) {
1034  av_log(s, AV_LOG_ERROR, "Failed to map buffer memory: %s\n",
1035  ff_vk_ret2str(ret));
1036  return AVERROR_EXTERNAL;
1037  }
1038  mem[i] = dst;
1039  }
1040 
1041  if (!invalidate)
1042  return 0;
1043 
1044  for (int i = 0; i < nb_buffers; i++) {
1045  const VkMappedMemoryRange ival_buf = {
1046  .sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,
1047  .memory = buf[i]->mem,
1048  .size = VK_WHOLE_SIZE,
1049  };
1050  if (buf[i]->flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)
1051  continue;
1052  inval_list[inval_count++] = ival_buf;
1053  }
1054 
1055  if (inval_count) {
1056  ret = vk->InvalidateMappedMemoryRanges(s->hwctx->act_dev, inval_count,
1057  inval_list);
1058  if (ret != VK_SUCCESS) {
1059  av_log(s, AV_LOG_ERROR, "Failed to invalidate memory: %s\n",
1060  ff_vk_ret2str(ret));
1061  return AVERROR_EXTERNAL;
1062  }
1063  }
1064 
1065  return 0;
1066 }
1067 
1068 int ff_vk_unmap_buffers(FFVulkanContext *s, FFVkBuffer **buf, int nb_buffers,
1069  int flush)
1070 {
1071  int err = 0;
1072  VkResult ret;
1073  FFVulkanFunctions *vk = &s->vkfn;
1074  VkMappedMemoryRange flush_list[64];
1075  int flush_count = 0;
1076 
1077  if (flush) {
1078  for (int i = 0; i < nb_buffers; i++) {
1079  const VkMappedMemoryRange flush_buf = {
1080  .sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,
1081  .memory = buf[i]->mem,
1082  .size = VK_WHOLE_SIZE,
1083  };
1084  if (buf[i]->flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)
1085  continue;
1086  flush_list[flush_count++] = flush_buf;
1087  }
1088  }
1089 
1090  if (flush_count) {
1091  ret = vk->FlushMappedMemoryRanges(s->hwctx->act_dev, flush_count,
1092  flush_list);
1093  if (ret != VK_SUCCESS) {
1094  av_log(s, AV_LOG_ERROR, "Failed to flush memory: %s\n",
1095  ff_vk_ret2str(ret));
1096  err = AVERROR_EXTERNAL; /* We still want to try to unmap them */
1097  }
1098  }
1099 
1100  for (int i = 0; i < nb_buffers; i++)
1101  vk->UnmapMemory(s->hwctx->act_dev, buf[i]->mem);
1102 
1103  return err;
1104 }
1105 
1107 {
1108  FFVulkanFunctions *vk = &s->vkfn;
1109 
1110  if (!buf || !s->hwctx)
1111  return;
1112 
1113  if (buf->mapped_mem)
1114  ff_vk_unmap_buffer(s, buf, 0);
1115  if (buf->buf != VK_NULL_HANDLE)
1116  vk->DestroyBuffer(s->hwctx->act_dev, buf->buf, s->hwctx->alloc);
1117  if (buf->mem != VK_NULL_HANDLE)
1118  vk->FreeMemory(s->hwctx->act_dev, buf->mem, s->hwctx->alloc);
1119 }
1120 
1121 static void free_data_buf(void *opaque, uint8_t *data)
1122 {
1123  FFVulkanContext *ctx = opaque;
1124  FFVkBuffer *buf = (FFVkBuffer *)data;
1125  ff_vk_free_buf(ctx, buf);
1126  av_free(data);
1127 }
1128 
1129 static AVBufferRef *alloc_data_buf(void *opaque, size_t size)
1130 {
1131  AVBufferRef *ref;
1132  uint8_t *buf = av_mallocz(size);
1133  if (!buf)
1134  return NULL;
1135 
1136  ref = av_buffer_create(buf, size, free_data_buf, opaque, 0);
1137  if (!ref)
1138  av_free(buf);
1139  return ref;
1140 }
1141 
1143  AVBufferRef **buf, VkBufferUsageFlags usage,
1144  void *create_pNext, size_t size,
1145  VkMemoryPropertyFlagBits mem_props)
1146 {
1147  int err;
1148  AVBufferRef *ref;
1149  FFVkBuffer *data;
1150 
1151  if (!(*buf_pool)) {
1152  *buf_pool = av_buffer_pool_init2(sizeof(FFVkBuffer), ctx,
1153  alloc_data_buf, NULL);
1154  if (!(*buf_pool))
1155  return AVERROR(ENOMEM);
1156  }
1157 
1158  *buf = ref = av_buffer_pool_get(*buf_pool);
1159  if (!ref)
1160  return AVERROR(ENOMEM);
1161 
1162  data = (FFVkBuffer *)ref->data;
1163  data->stage = VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT;
1164  data->access = VK_ACCESS_2_NONE;
1165 
1166  if (data->size >= size)
1167  return 0;
1168 
1170  memset(data, 0, sizeof(*data));
1171 
1172  av_log(ctx, AV_LOG_DEBUG, "Allocating buffer of %"SIZE_SPECIFIER" bytes for pool %p\n",
1173  size, *buf_pool);
1174 
1175  err = ff_vk_create_buf(ctx, data, size,
1176  create_pNext, NULL, usage,
1177  mem_props);
1178  if (err < 0) {
1179  av_buffer_unref(&ref);
1180  return err;
1181  }
1182 
1183  if (mem_props & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) {
1184  err = ff_vk_map_buffer(ctx, data, &data->mapped_mem, 0);
1185  if (err < 0) {
1186  av_buffer_unref(&ref);
1187  return err;
1188  }
1189  }
1190 
1191  return 0;
1192 }
1193 
1195  VkShaderStageFlagBits stage)
1196 {
1197  VkPushConstantRange *pc;
1198 
1199  pl->push_consts = av_realloc_array(pl->push_consts, sizeof(*pl->push_consts),
1200  pl->push_consts_num + 1);
1201  if (!pl->push_consts)
1202  return AVERROR(ENOMEM);
1203 
1204  pc = &pl->push_consts[pl->push_consts_num++];
1205  memset(pc, 0, sizeof(*pc));
1206 
1207  pc->stageFlags = stage;
1208  pc->offset = offset;
1209  pc->size = size;
1210 
1211  return 0;
1212 }
1213 
1214 int ff_vk_init_sampler(FFVulkanContext *s, VkSampler *sampler,
1215  int unnorm_coords, VkFilter filt)
1216 {
1217  VkResult ret;
1218  FFVulkanFunctions *vk = &s->vkfn;
1219 
1220  VkSamplerCreateInfo sampler_info = {
1221  .sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,
1222  .magFilter = filt,
1223  .minFilter = sampler_info.magFilter,
1224  .mipmapMode = unnorm_coords ? VK_SAMPLER_MIPMAP_MODE_NEAREST :
1225  VK_SAMPLER_MIPMAP_MODE_LINEAR,
1226  .addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
1227  .addressModeV = sampler_info.addressModeU,
1228  .addressModeW = sampler_info.addressModeU,
1229  .anisotropyEnable = VK_FALSE,
1230  .compareOp = VK_COMPARE_OP_NEVER,
1231  .borderColor = VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK,
1232  .unnormalizedCoordinates = unnorm_coords,
1233  };
1234 
1235  ret = vk->CreateSampler(s->hwctx->act_dev, &sampler_info,
1236  s->hwctx->alloc, sampler);
1237  if (ret != VK_SUCCESS) {
1238  av_log(s, AV_LOG_ERROR, "Unable to init sampler: %s\n",
1239  ff_vk_ret2str(ret));
1240  return AVERROR_EXTERNAL;
1241  }
1242 
1243  return 0;
1244 }
1245 
1247 {
1255  return 1;
1256  return 0;
1257 }
1258 
1260 {
1262  const int high = desc->comp[0].depth > 8;
1263  return high ? "rgba16f" : "rgba8";
1264 }
1265 
1266 typedef struct ImageViewCtx {
1268  VkImageView views[];
1269 } ImageViewCtx;
1270 
1271 static void destroy_imageviews(void *opaque, uint8_t *data)
1272 {
1273  FFVulkanContext *s = opaque;
1274  FFVulkanFunctions *vk = &s->vkfn;
1275  ImageViewCtx *iv = (ImageViewCtx *)data;
1276 
1277  for (int i = 0; i < iv->nb_views; i++)
1278  vk->DestroyImageView(s->hwctx->act_dev, iv->views[i], s->hwctx->alloc);
1279 
1280  av_free(iv);
1281 }
1282 
1284  VkImageView views[AV_NUM_DATA_POINTERS],
1285  AVFrame *f)
1286 {
1287  int err;
1288  VkResult ret;
1289  AVBufferRef *buf;
1290  FFVulkanFunctions *vk = &s->vkfn;
1291  AVHWFramesContext *hwfc = (AVHWFramesContext *)f->hw_frames_ctx->data;
1292  const VkFormat *rep_fmts = av_vkfmt_from_pixfmt(hwfc->sw_format);
1293  AVVkFrame *vkf = (AVVkFrame *)f->data[0];
1294  const int nb_images = ff_vk_count_images(vkf);
1295  const int nb_planes = av_pix_fmt_count_planes(hwfc->sw_format);
1296 
1297  const size_t buf_size = sizeof(int) + nb_planes*sizeof(VkImageView);
1298  ImageViewCtx *iv = av_mallocz(buf_size);
1299  if (!iv)
1300  return AVERROR(ENOMEM);
1301 
1302  for (int i = 0; i < nb_planes; i++) {
1303  VkImageAspectFlags plane_aspect[] = { VK_IMAGE_ASPECT_COLOR_BIT,
1304  VK_IMAGE_ASPECT_PLANE_0_BIT,
1305  VK_IMAGE_ASPECT_PLANE_1_BIT,
1306  VK_IMAGE_ASPECT_PLANE_2_BIT, };
1307 
1308  VkImageViewCreateInfo view_create_info = {
1309  .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
1310  .pNext = NULL,
1311  .image = vkf->img[FFMIN(i, nb_images - 1)],
1312  .viewType = VK_IMAGE_VIEW_TYPE_2D,
1313  .format = rep_fmts[i],
1314  .components = ff_comp_identity_map,
1315  .subresourceRange = {
1316  .aspectMask = plane_aspect[(nb_planes != nb_images) +
1317  i*(nb_planes != nb_images)],
1318  .levelCount = 1,
1319  .layerCount = 1,
1320  },
1321  };
1322 
1323  ret = vk->CreateImageView(s->hwctx->act_dev, &view_create_info,
1324  s->hwctx->alloc, &iv->views[i]);
1325  if (ret != VK_SUCCESS) {
1326  av_log(s, AV_LOG_ERROR, "Failed to create imageview: %s\n",
1327  ff_vk_ret2str(ret));
1328  err = AVERROR_EXTERNAL;
1329  goto fail;
1330  }
1331 
1332  iv->nb_views++;
1333  }
1334 
1335  buf = av_buffer_create((uint8_t *)iv, buf_size, destroy_imageviews, s, 0);
1336  if (!buf) {
1337  err = AVERROR(ENOMEM);
1338  goto fail;
1339  }
1340 
1341  /* Add to queue dependencies */
1342  err = ff_vk_exec_add_dep_buf(s, e, &buf, 1, 0);
1343  if (err < 0)
1344  av_buffer_unref(&buf);
1345 
1346  memcpy(views, iv->views, nb_planes*sizeof(*views));
1347 
1348  return err;
1349 
1350 fail:
1351  for (int i = 0; i < iv->nb_views; i++)
1352  vk->DestroyImageView(s->hwctx->act_dev, iv->views[i], s->hwctx->alloc);
1353  av_free(iv);
1354  return err;
1355 }
1356 
1358  AVFrame *pic, VkImageMemoryBarrier2 *bar, int *nb_bar,
1359  VkPipelineStageFlags src_stage,
1360  VkPipelineStageFlags dst_stage,
1361  VkAccessFlagBits new_access,
1362  VkImageLayout new_layout,
1363  uint32_t new_qf)
1364 {
1365  int found = -1;
1366  AVVkFrame *vkf = (AVVkFrame *)pic->data[0];
1367  const int nb_images = ff_vk_count_images(vkf);
1368  for (int i = 0; i < e->nb_frame_deps; i++)
1369  if (e->frame_deps[i]->data[0] == pic->data[0]) {
1370  if (e->frame_update[i])
1371  found = i;
1372  break;
1373  }
1374 
1375  for (int i = 0; i < nb_images; i++) {
1376  bar[*nb_bar] = (VkImageMemoryBarrier2) {
1377  .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2,
1378  .pNext = NULL,
1379  .srcStageMask = src_stage,
1380  .dstStageMask = dst_stage,
1381  .srcAccessMask = found >= 0 ? e->access_dst[found] : vkf->access[i],
1382  .dstAccessMask = new_access,
1383  .oldLayout = found >= 0 ? e->layout_dst[found] : vkf->layout[0],
1384  .newLayout = new_layout,
1385  .srcQueueFamilyIndex = found >= 0 ? e->queue_family_dst[found] : vkf->queue_family[0],
1386  .dstQueueFamilyIndex = new_qf,
1387  .image = vkf->img[i],
1388  .subresourceRange = (VkImageSubresourceRange) {
1389  .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
1390  .layerCount = 1,
1391  .levelCount = 1,
1392  },
1393  };
1394  *nb_bar += 1;
1395  }
1396 
1397  ff_vk_exec_update_frame(s, e, pic, &bar[*nb_bar - nb_images], NULL);
1398 }
1399 
1401  VkShaderStageFlags stage, uint32_t required_subgroup_size)
1402 {
1404 
1405  shd->shader.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
1406  shd->shader.stage = stage;
1407 
1408  if (required_subgroup_size) {
1409  shd->shader.flags |= VK_PIPELINE_SHADER_STAGE_CREATE_REQUIRE_FULL_SUBGROUPS_BIT;
1410  shd->shader.pNext = &shd->subgroup_info;
1411  shd->subgroup_info.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_REQUIRED_SUBGROUP_SIZE_CREATE_INFO;
1412  shd->subgroup_info.requiredSubgroupSize = required_subgroup_size;
1413  }
1414 
1415  shd->name = name;
1416 
1417  GLSLF(0, #version %i ,460);
1418  GLSLC(0, #define IS_WITHIN(v1, v2) ((v1.x < v2.x) && (v1.y < v2.y)) );
1419  GLSLC(0, );
1420  GLSLC(0, #extension GL_EXT_buffer_reference : require );
1421  GLSLC(0, #extension GL_EXT_buffer_reference2 : require );
1422 
1423  return 0;
1424 }
1425 
1426 void ff_vk_shader_set_compute_sizes(FFVkSPIRVShader *shd, int x, int y, int z)
1427 {
1428  shd->local_size[0] = x;
1429  shd->local_size[1] = y;
1430  shd->local_size[2] = z;
1431 
1432  av_bprintf(&shd->src, "layout (local_size_x = %i, "
1433  "local_size_y = %i, local_size_z = %i) in;\n\n",
1434  shd->local_size[0], shd->local_size[1], shd->local_size[2]);
1435 }
1436 
1437 void ff_vk_shader_print(void *ctx, FFVkSPIRVShader *shd, int prio)
1438 {
1439  int line = 0;
1440  const char *p = shd->src.str;
1441  const char *start = p;
1442  const size_t len = strlen(p);
1443 
1444  AVBPrint buf;
1446 
1447  for (int i = 0; i < len; i++) {
1448  if (p[i] == '\n') {
1449  av_bprintf(&buf, "%i\t", ++line);
1450  av_bprint_append_data(&buf, start, &p[i] - start + 1);
1451  start = &p[i + 1];
1452  }
1453  }
1454 
1455  av_log(ctx, prio, "Shader %s: \n%s", shd->name, buf.str);
1456  av_bprint_finalize(&buf, NULL);
1457 }
1458 
1460 {
1461  FFVulkanFunctions *vk = &s->vkfn;
1462  av_bprint_finalize(&shd->src, NULL);
1463 
1464  if (shd->shader.module)
1465  vk->DestroyShaderModule(s->hwctx->act_dev, shd->shader.module, s->hwctx->alloc);
1466 }
1467 
1469  uint8_t *spirv, size_t spirv_size, const char *entrypoint)
1470 {
1471  VkResult ret;
1472  FFVulkanFunctions *vk = &s->vkfn;
1473  VkShaderModuleCreateInfo shader_create;
1474 
1475  shd->shader.pName = entrypoint;
1476 
1477  av_log(s, AV_LOG_VERBOSE, "Shader %s compiled! Size: %zu bytes\n",
1478  shd->name, spirv_size);
1479 
1480  shader_create.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
1481  shader_create.pNext = NULL;
1482  shader_create.codeSize = spirv_size;
1483  shader_create.flags = 0;
1484  shader_create.pCode = (void *)spirv;
1485 
1486  ret = vk->CreateShaderModule(s->hwctx->act_dev, &shader_create, NULL,
1487  &shd->shader.module);
1488  if (ret != VK_SUCCESS) {
1489  av_log(s, AV_LOG_VERBOSE, "Error creating shader module: %s\n",
1490  ff_vk_ret2str(ret));
1491  return AVERROR_EXTERNAL;
1492  }
1493 
1494  return 0;
1495 }
1496 
1497 static const struct descriptor_props {
1498  size_t struct_size; /* Size of the opaque which updates the descriptor */
1499  const char *type;
1501  int mem_quali; /* Can use a memory qualifier */
1502  int dim_needed; /* Must indicate dimension */
1503  int buf_content; /* Must indicate buffer contents */
1504 } descriptor_props[] = {
1505  [VK_DESCRIPTOR_TYPE_SAMPLER] = { sizeof(VkDescriptorImageInfo), "sampler", 1, 0, 0, 0, },
1506  [VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE] = { sizeof(VkDescriptorImageInfo), "texture", 1, 0, 1, 0, },
1507  [VK_DESCRIPTOR_TYPE_STORAGE_IMAGE] = { sizeof(VkDescriptorImageInfo), "image", 1, 1, 1, 0, },
1508  [VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT] = { sizeof(VkDescriptorImageInfo), "subpassInput", 1, 0, 0, 0, },
1509  [VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER] = { sizeof(VkDescriptorImageInfo), "sampler", 1, 0, 1, 0, },
1510  [VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER] = { sizeof(VkDescriptorBufferInfo), NULL, 1, 0, 0, 1, },
1511  [VK_DESCRIPTOR_TYPE_STORAGE_BUFFER] = { sizeof(VkDescriptorBufferInfo), "buffer", 0, 1, 0, 1, },
1512  [VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC] = { sizeof(VkDescriptorBufferInfo), NULL, 1, 0, 0, 1, },
1513  [VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC] = { sizeof(VkDescriptorBufferInfo), "buffer", 0, 1, 0, 1, },
1514  [VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER] = { sizeof(VkBufferView), "samplerBuffer", 1, 0, 0, 0, },
1515  [VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER] = { sizeof(VkBufferView), "imageBuffer", 1, 0, 0, 0, },
1516 };
1517 
1519  FFVkSPIRVShader *shd,
1521  int singular, int print_to_shader_only)
1522 {
1523  int has_sampler = 0;
1525 
1526  if (print_to_shader_only)
1527  goto print;
1528 
1529  /* Actual layout allocated for the pipeline */
1530  set = av_realloc_array(pl->desc_set, sizeof(*pl->desc_set),
1531  pl->nb_descriptor_sets + 1);
1532  if (!set)
1533  return AVERROR(ENOMEM);
1534  pl->desc_set = set;
1535 
1536  set = &set[pl->nb_descriptor_sets];
1537  memset(set, 0, sizeof(*set));
1538 
1539  set->binding = av_calloc(nb, sizeof(*set->binding));
1540  if (!set->binding)
1541  return AVERROR(ENOMEM);
1542 
1543  set->binding_offset = av_calloc(nb, sizeof(*set->binding_offset));
1544  if (!set->binding_offset) {
1545  av_freep(&set->binding);
1546  return AVERROR(ENOMEM);
1547  }
1548 
1549  for (int i = 0; i < nb; i++) {
1550  set->binding[i].binding = i;
1551  set->binding[i].descriptorType = desc[i].type;
1552  set->binding[i].descriptorCount = FFMAX(desc[i].elems, 1);
1553  set->binding[i].stageFlags = desc[i].stages;
1554  set->binding[i].pImmutableSamplers = desc[i].samplers;
1555 
1556  if (desc[i].type == VK_DESCRIPTOR_TYPE_SAMPLER ||
1557  desc[i].type == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
1558  has_sampler |= 1;
1559  }
1560 
1561  set->usage = VK_BUFFER_USAGE_RESOURCE_DESCRIPTOR_BUFFER_BIT_EXT |
1562  VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT;
1563  if (has_sampler)
1564  set->usage |= VK_BUFFER_USAGE_SAMPLER_DESCRIPTOR_BUFFER_BIT_EXT;
1565 
1566  if (!(s->extensions & FF_VK_EXT_DESCRIPTOR_BUFFER)) {
1567  for (int i = 0; i < nb; i++) {
1568  int j;
1569  VkDescriptorPoolSize *desc_pool_size;
1570  for (j = 0; j < pl->nb_desc_pool_size; j++)
1571  if (pl->desc_pool_size[j].type == desc[i].type)
1572  break;
1573  if (j >= pl->nb_desc_pool_size) {
1574  desc_pool_size = av_realloc_array(pl->desc_pool_size,
1575  sizeof(*desc_pool_size),
1576  pl->nb_desc_pool_size + 1);
1577  if (!desc_pool_size)
1578  return AVERROR(ENOMEM);
1579 
1580  pl->desc_pool_size = desc_pool_size;
1581  pl->nb_desc_pool_size++;
1582  memset(&desc_pool_size[j], 0, sizeof(VkDescriptorPoolSize));
1583  }
1584  pl->desc_pool_size[j].type = desc[i].type;
1585  pl->desc_pool_size[j].descriptorCount += FFMAX(desc[i].elems, 1);
1586  }
1587  }
1588 
1589  set->singular = singular;
1590  set->nb_bindings = nb;
1591  pl->nb_descriptor_sets++;
1592 
1593 print:
1594  /* Write shader info */
1595  for (int i = 0; i < nb; i++) {
1596  const struct descriptor_props *prop = &descriptor_props[desc[i].type];
1597  GLSLA("layout (set = %i, binding = %i", pl->nb_descriptor_sets - 1, i);
1598 
1599  if (desc[i].mem_layout)
1600  GLSLA(", %s", desc[i].mem_layout);
1601  GLSLA(")");
1602 
1603  if (prop->is_uniform)
1604  GLSLA(" uniform");
1605 
1606  if (prop->mem_quali && desc[i].mem_quali)
1607  GLSLA(" %s", desc[i].mem_quali);
1608 
1609  if (prop->type)
1610  GLSLA(" %s", prop->type);
1611 
1612  if (prop->dim_needed)
1613  GLSLA("%iD", desc[i].dimensions);
1614 
1615  GLSLA(" %s", desc[i].name);
1616 
1617  if (prop->buf_content)
1618  GLSLA(" {\n %s\n}", desc[i].buf_content);
1619  else if (desc[i].elems > 0)
1620  GLSLA("[%i]", desc[i].elems);
1621 
1622  GLSLA(";");
1623  GLSLA("\n");
1624  }
1625  GLSLA("\n");
1626 
1627  return 0;
1628 }
1629 
1631  FFVulkanPipeline *pl)
1632 {
1633  int err;
1634 
1635  if (!pl->nb_descriptor_sets)
1636  return 0;
1637 
1638  if (s->extensions & FF_VK_EXT_DESCRIPTOR_BUFFER) {
1639  pl->desc_bind = av_calloc(pl->nb_descriptor_sets, sizeof(*pl->desc_bind));
1640  if (!pl->desc_bind)
1641  return AVERROR(ENOMEM);
1642 
1644  sizeof(*pl->bound_buffer_indices));
1645  if (!pl->bound_buffer_indices)
1646  return AVERROR(ENOMEM);
1647 
1648  for (int i = 0; i < pl->nb_descriptor_sets; i++) {
1650  int nb = set->singular ? 1 : pool->pool_size;
1651 
1652  err = ff_vk_create_buf(s, &set->buf, set->aligned_size*nb,
1653  NULL, NULL, set->usage,
1654  VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT |
1655  VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
1656  VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
1657  if (err < 0)
1658  return err;
1659 
1660  err = ff_vk_map_buffer(s, &set->buf, &set->desc_mem, 0);
1661  if (err < 0)
1662  return err;
1663 
1664  pl->desc_bind[i] = (VkDescriptorBufferBindingInfoEXT) {
1665  .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_BUFFER_BINDING_INFO_EXT,
1666  .usage = set->usage,
1667  .address = set->buf.address,
1668  };
1669 
1670  pl->bound_buffer_indices[i] = i;
1671  }
1672  } else if (!pl->use_push) {
1673  VkResult ret;
1674  FFVulkanFunctions *vk = &s->vkfn;
1675  VkDescriptorSetLayout *tmp_layouts;
1676  VkDescriptorSetAllocateInfo set_alloc_info;
1677  VkDescriptorPoolCreateInfo pool_create_info;
1678 
1679  for (int i = 0; i < pl->nb_desc_pool_size; i++)
1680  pl->desc_pool_size[i].descriptorCount *= pool->pool_size;
1681 
1682  pool_create_info = (VkDescriptorPoolCreateInfo) {
1683  .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
1684  .flags = 0,
1685  .pPoolSizes = pl->desc_pool_size,
1686  .poolSizeCount = pl->nb_desc_pool_size,
1687  .maxSets = pl->nb_descriptor_sets*pool->pool_size,
1688  };
1689 
1690  ret = vk->CreateDescriptorPool(s->hwctx->act_dev, &pool_create_info,
1691  s->hwctx->alloc, &pl->desc_pool);
1692  if (ret != VK_SUCCESS) {
1693  av_log(s, AV_LOG_ERROR, "Unable to create descriptor pool: %s\n",
1694  ff_vk_ret2str(ret));
1695  return AVERROR_EXTERNAL;
1696  }
1697 
1698  tmp_layouts = av_malloc_array(pool_create_info.maxSets, sizeof(*tmp_layouts));
1699  if (!tmp_layouts)
1700  return AVERROR(ENOMEM);
1701 
1702  /* Colate each execution context's descriptor set layouts */
1703  for (int i = 0; i < pool->pool_size; i++)
1704  for (int j = 0; j < pl->nb_descriptor_sets; j++)
1705  tmp_layouts[i*pl->nb_descriptor_sets + j] = pl->desc_layout[j];
1706 
1707  set_alloc_info = (VkDescriptorSetAllocateInfo) {
1708  .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
1709  .descriptorPool = pl->desc_pool,
1710  .pSetLayouts = tmp_layouts,
1711  .descriptorSetCount = pool_create_info.maxSets,
1712  };
1713 
1714  pl->desc_sets = av_malloc_array(pool_create_info.maxSets,
1715  sizeof(*tmp_layouts));
1716  if (!pl->desc_sets) {
1717  av_free(tmp_layouts);
1718  return AVERROR(ENOMEM);
1719  }
1720  ret = vk->AllocateDescriptorSets(s->hwctx->act_dev, &set_alloc_info,
1721  pl->desc_sets);
1722  av_free(tmp_layouts);
1723  if (ret != VK_SUCCESS) {
1724  av_log(s, AV_LOG_ERROR, "Unable to allocate descriptor set: %s\n",
1725  ff_vk_ret2str(ret));
1726  av_freep(&pl->desc_sets);
1727  return AVERROR_EXTERNAL;
1728  }
1729 
1730  pl->assoc_pool = pool;
1731  }
1732 
1733  return 0;
1734 }
1735 
1738  int bind_idx, int array_idx,
1739  VkDescriptorGetInfoEXT *desc_get_info,
1740  size_t desc_size)
1741 {
1742  FFVulkanFunctions *vk = &s->vkfn;
1743  const size_t exec_offset = set->singular ? 0 : set->aligned_size*e->idx;
1744  void *desc = set->desc_mem + /* Base */
1745  exec_offset + /* Execution context */
1746  set->binding_offset[bind_idx] + /* Descriptor binding */
1747  array_idx*desc_size; /* Array position */
1748 
1749  vk->GetDescriptorEXT(s->hwctx->act_dev, desc_get_info, desc_size, desc);
1750 }
1751 
1753  FFVulkanPipeline *pl,
1754  FFVkExecContext *e,
1755  FFVulkanDescriptorSet *desc_set, int set,
1756  VkWriteDescriptorSet *write_info)
1757 {
1758  FFVulkanFunctions *vk = &s->vkfn;
1759  if (desc_set->singular) {
1760  for (int i = 0; i < pl->assoc_pool->pool_size; i++) {
1761  write_info->dstSet = pl->desc_sets[i*pl->nb_descriptor_sets + set];
1762  vk->UpdateDescriptorSets(s->hwctx->act_dev, 1, write_info, 0, NULL);
1763  }
1764  } else {
1765  if (pl->use_push) {
1766  vk->CmdPushDescriptorSetKHR(e->buf,
1767  pl->bind_point,
1768  pl->pipeline_layout,
1769  set, 1,
1770  write_info);
1771  } else {
1772  write_info->dstSet = pl->desc_sets[e->idx*pl->nb_descriptor_sets + set];
1773  vk->UpdateDescriptorSets(s->hwctx->act_dev, 1, write_info, 0, NULL);
1774  }
1775  }
1776 }
1777 
1779  FFVkExecContext *e, int set, int bind, int offs,
1780  VkImageView view, VkImageLayout layout,
1781  VkSampler sampler)
1782 {
1783  FFVulkanDescriptorSet *desc_set = &pl->desc_set[set];
1784 
1785  if (s->extensions & FF_VK_EXT_DESCRIPTOR_BUFFER) {
1786  VkDescriptorGetInfoEXT desc_get_info = {
1787  .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_GET_INFO_EXT,
1788  .type = desc_set->binding[bind].descriptorType,
1789  };
1790  VkDescriptorImageInfo desc_img_info = {
1791  .imageView = view,
1792  .sampler = sampler,
1793  .imageLayout = layout,
1794  };
1795  size_t desc_size;
1796 
1797  switch (desc_get_info.type) {
1798  case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
1799  desc_get_info.data.pSampledImage = &desc_img_info;
1800  desc_size = s->desc_buf_props.sampledImageDescriptorSize;
1801  break;
1802  case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
1803  desc_get_info.data.pStorageImage = &desc_img_info;
1804  desc_size = s->desc_buf_props.storageImageDescriptorSize;
1805  break;
1806  case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
1807  desc_get_info.data.pInputAttachmentImage = &desc_img_info;
1808  desc_size = s->desc_buf_props.inputAttachmentDescriptorSize;
1809  break;
1810  case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
1811  desc_get_info.data.pCombinedImageSampler = &desc_img_info;
1812  desc_size = s->desc_buf_props.combinedImageSamplerDescriptorSize;
1813  break;
1814  default:
1815  av_log(s, AV_LOG_ERROR, "Invalid descriptor type at set %i binding %i: %i!\n",
1816  set, bind, desc_get_info.type);
1817  return AVERROR(EINVAL);
1818  break;
1819  };
1820 
1821  update_set_descriptor(s, e, desc_set, bind, offs,
1822  &desc_get_info, desc_size);
1823  } else {
1824  VkDescriptorImageInfo desc_pool_write_info_img = {
1825  .sampler = sampler,
1826  .imageView = view,
1827  .imageLayout = layout,
1828  };
1829  VkWriteDescriptorSet desc_pool_write_info = {
1830  .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
1831  .dstBinding = bind,
1832  .descriptorCount = 1,
1833  .dstArrayElement = offs,
1834  .descriptorType = desc_set->binding[bind].descriptorType,
1835  .pImageInfo = &desc_pool_write_info_img,
1836  };
1837  update_set_pool_write(s, pl, e, desc_set, set, &desc_pool_write_info);
1838  }
1839 
1840  return 0;
1841 }
1842 
1844  FFVkExecContext *e, int set, int bind, int elem,
1845  FFVkBuffer *buf, VkDeviceSize offset, VkDeviceSize len,
1846  VkFormat fmt)
1847 {
1848  FFVulkanDescriptorSet *desc_set = &pl->desc_set[set];
1849 
1850  if (s->extensions & FF_VK_EXT_DESCRIPTOR_BUFFER) {
1851  VkDescriptorGetInfoEXT desc_get_info = {
1852  .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_GET_INFO_EXT,
1853  .type = desc_set->binding[bind].descriptorType,
1854  };
1855  VkDescriptorAddressInfoEXT desc_buf_info = {
1856  .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_ADDRESS_INFO_EXT,
1857  .address = buf->address + offset,
1858  .range = len,
1859  .format = fmt,
1860  };
1861  size_t desc_size;
1862 
1863  switch (desc_get_info.type) {
1864  case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
1865  desc_get_info.data.pUniformBuffer = &desc_buf_info;
1866  desc_size = s->desc_buf_props.uniformBufferDescriptorSize;
1867  break;
1868  case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
1869  desc_get_info.data.pStorageBuffer = &desc_buf_info;
1870  desc_size = s->desc_buf_props.storageBufferDescriptorSize;
1871  break;
1872  case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
1873  desc_get_info.data.pUniformTexelBuffer = &desc_buf_info;
1874  desc_size = s->desc_buf_props.uniformTexelBufferDescriptorSize;
1875  break;
1876  case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
1877  desc_get_info.data.pStorageTexelBuffer = &desc_buf_info;
1878  desc_size = s->desc_buf_props.storageTexelBufferDescriptorSize;
1879  break;
1880  default:
1881  av_log(s, AV_LOG_ERROR, "Invalid descriptor type at set %i binding %i: %i!\n",
1882  set, bind, desc_get_info.type);
1883  return AVERROR(EINVAL);
1884  break;
1885  };
1886 
1887  update_set_descriptor(s, e, desc_set, bind, elem, &desc_get_info, desc_size);
1888  } else {
1889  VkDescriptorBufferInfo desc_pool_write_info_buf = {
1890  .buffer = buf->buf,
1891  .offset = offset,
1892  .range = len,
1893  };
1894  VkWriteDescriptorSet desc_pool_write_info = {
1895  .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
1896  .dstBinding = bind,
1897  .descriptorCount = 1,
1898  .dstArrayElement = elem,
1899  .descriptorType = desc_set->binding[bind].descriptorType,
1900  .pBufferInfo = &desc_pool_write_info_buf,
1901  };
1902  update_set_pool_write(s, pl, e, desc_set, set, &desc_pool_write_info);
1903  }
1904 
1905  return 0;
1906 }
1907 
1909  FFVkExecContext *e, AVFrame *f,
1910  VkImageView *views, int set, int binding,
1911  VkImageLayout layout, VkSampler sampler)
1912 {
1913  AVHWFramesContext *hwfc = (AVHWFramesContext *)f->hw_frames_ctx->data;
1914  const int nb_planes = av_pix_fmt_count_planes(hwfc->sw_format);
1915 
1916  for (int i = 0; i < nb_planes; i++)
1917  vk_set_descriptor_image(s, pl, e, set, binding, i,
1918  views[i], layout, sampler);
1919 }
1920 
1922  FFVulkanPipeline *pl,
1923  VkShaderStageFlagBits stage,
1924  int offset, size_t size, void *src)
1925 {
1926  FFVulkanFunctions *vk = &s->vkfn;
1927  vk->CmdPushConstants(e->buf, pl->pipeline_layout,
1928  stage, offset, size, src);
1929 }
1930 
1932 {
1933  VkResult ret;
1934  FFVulkanFunctions *vk = &s->vkfn;
1935 
1937  sizeof(*pl->desc_layout));
1938  if (!pl->desc_layout)
1939  return AVERROR(ENOMEM);
1940 
1941  if (!(s->extensions & FF_VK_EXT_DESCRIPTOR_BUFFER)) {
1942  int has_singular = 0;
1943  for (int i = 0; i < pl->nb_descriptor_sets; i++) {
1944  if (pl->desc_set[i].singular) {
1945  has_singular = 1;
1946  break;
1947  }
1948  }
1949  pl->use_push = (s->extensions & FF_VK_EXT_PUSH_DESCRIPTOR) &&
1950  (pl->nb_descriptor_sets == 1) &&
1951  !has_singular;
1952  }
1953 
1954  for (int i = 0; i < pl->nb_descriptor_sets; i++) {
1956  VkDescriptorSetLayoutCreateInfo desc_layout_create = {
1957  .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
1958  .bindingCount = set->nb_bindings,
1959  .pBindings = set->binding,
1960  .flags = (s->extensions & FF_VK_EXT_DESCRIPTOR_BUFFER) ?
1961  VK_DESCRIPTOR_SET_LAYOUT_CREATE_DESCRIPTOR_BUFFER_BIT_EXT :
1962  (pl->use_push) ?
1963  VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR :
1964  0x0,
1965  };
1966 
1967  ret = vk->CreateDescriptorSetLayout(s->hwctx->act_dev,
1968  &desc_layout_create,
1969  s->hwctx->alloc,
1970  &pl->desc_layout[i]);
1971  if (ret != VK_SUCCESS) {
1972  av_log(s, AV_LOG_ERROR, "Unable to create descriptor set layout: %s",
1973  ff_vk_ret2str(ret));
1974  return AVERROR_EXTERNAL;
1975  }
1976 
1977  if (s->extensions & FF_VK_EXT_DESCRIPTOR_BUFFER) {
1978  vk->GetDescriptorSetLayoutSizeEXT(s->hwctx->act_dev, pl->desc_layout[i],
1979  &set->layout_size);
1980 
1981  set->aligned_size = FFALIGN(set->layout_size,
1982  s->desc_buf_props.descriptorBufferOffsetAlignment);
1983 
1984  for (int j = 0; j < set->nb_bindings; j++)
1985  vk->GetDescriptorSetLayoutBindingOffsetEXT(s->hwctx->act_dev,
1986  pl->desc_layout[i],
1987  j,
1988  &set->binding_offset[j]);
1989  }
1990  }
1991 
1992  return 0;
1993 }
1994 
1996 {
1997  VkResult ret;
1998  FFVulkanFunctions *vk = &s->vkfn;
1999  VkPipelineLayoutCreateInfo pipeline_layout_info;
2000 
2001  /* Finally create the pipeline layout */
2002  pipeline_layout_info = (VkPipelineLayoutCreateInfo) {
2003  .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
2004  .pSetLayouts = pl->desc_layout,
2005  .setLayoutCount = pl->nb_descriptor_sets,
2006  .pushConstantRangeCount = pl->push_consts_num,
2007  .pPushConstantRanges = pl->push_consts,
2008  };
2009 
2010  ret = vk->CreatePipelineLayout(s->hwctx->act_dev, &pipeline_layout_info,
2011  s->hwctx->alloc, &pl->pipeline_layout);
2012  if (ret != VK_SUCCESS) {
2013  av_log(s, AV_LOG_ERROR, "Unable to init pipeline layout: %s\n",
2014  ff_vk_ret2str(ret));
2015  return AVERROR_EXTERNAL;
2016  }
2017 
2018  return 0;
2019 }
2020 
2022  FFVkSPIRVShader *shd)
2023 {
2024  int err;
2025  VkResult ret;
2026  FFVulkanFunctions *vk = &s->vkfn;
2027 
2028  VkComputePipelineCreateInfo pipeline_create_info;
2029 
2030  err = init_descriptors(s, pl);
2031  if (err < 0)
2032  return err;
2033 
2034  err = init_pipeline_layout(s, pl);
2035  if (err < 0)
2036  return err;
2037 
2038  pipeline_create_info = (VkComputePipelineCreateInfo) {
2039  .sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,
2040  .flags = (s->extensions & FF_VK_EXT_DESCRIPTOR_BUFFER) ?
2041  VK_PIPELINE_CREATE_DESCRIPTOR_BUFFER_BIT_EXT : 0x0,
2042  .layout = pl->pipeline_layout,
2043  .stage = shd->shader,
2044  };
2045 
2046  ret = vk->CreateComputePipelines(s->hwctx->act_dev, VK_NULL_HANDLE, 1,
2047  &pipeline_create_info,
2048  s->hwctx->alloc, &pl->pipeline);
2049  if (ret != VK_SUCCESS) {
2050  av_log(s, AV_LOG_ERROR, "Unable to init compute pipeline: %s\n",
2051  ff_vk_ret2str(ret));
2052  return AVERROR_EXTERNAL;
2053  }
2054 
2055  pl->bind_point = VK_PIPELINE_BIND_POINT_COMPUTE;
2056  pl->wg_size[0] = shd->local_size[0];
2057  pl->wg_size[1] = shd->local_size[1];
2058  pl->wg_size[2] = shd->local_size[2];
2059 
2060  return 0;
2061 }
2062 
2064  FFVulkanPipeline *pl)
2065 {
2066  FFVulkanFunctions *vk = &s->vkfn;
2067  VkDeviceSize offsets[1024];
2068 
2069  /* Bind pipeline */
2070  vk->CmdBindPipeline(e->buf, pl->bind_point, pl->pipeline);
2071 
2072  if (pl->nb_descriptor_sets) {
2073  if (s->extensions & FF_VK_EXT_DESCRIPTOR_BUFFER) {
2074  for (int i = 0; i < pl->nb_descriptor_sets; i++)
2075  offsets[i] = pl->desc_set[i].singular ? 0 : pl->desc_set[i].aligned_size*e->idx;
2076 
2077  /* Bind descriptor buffers */
2078  vk->CmdBindDescriptorBuffersEXT(e->buf, pl->nb_descriptor_sets, pl->desc_bind);
2079  /* Binding offsets */
2080  vk->CmdSetDescriptorBufferOffsetsEXT(e->buf, pl->bind_point, pl->pipeline_layout,
2081  0, pl->nb_descriptor_sets,
2083  } else if (!pl->use_push) {
2084  vk->CmdBindDescriptorSets(e->buf, pl->bind_point, pl->pipeline_layout,
2085  0, pl->nb_descriptor_sets,
2086  &pl->desc_sets[e->idx*pl->nb_descriptor_sets],
2087  0, NULL);
2088  }
2089  }
2090 }
2091 
2093 {
2094  FFVulkanFunctions *vk = &s->vkfn;
2095 
2096  if (pl->pipeline)
2097  vk->DestroyPipeline(s->hwctx->act_dev, pl->pipeline, s->hwctx->alloc);
2098  if (pl->pipeline_layout)
2099  vk->DestroyPipelineLayout(s->hwctx->act_dev, pl->pipeline_layout,
2100  s->hwctx->alloc);
2101 
2102  for (int i = 0; i < pl->nb_descriptor_sets; i++) {
2104  if (set->buf.mem)
2105  ff_vk_unmap_buffer(s, &set->buf, 0);
2106  ff_vk_free_buf(s, &set->buf);
2107  av_free(set->binding);
2108  av_free(set->binding_offset);
2109  }
2110 
2111  for (int i = 0; i < pl->nb_descriptor_sets; i++)
2112  if (pl->desc_layout[i])
2113  vk->DestroyDescriptorSetLayout(s->hwctx->act_dev, pl->desc_layout[i],
2114  s->hwctx->alloc);
2115 
2116  if (pl->desc_pool)
2117  vk->DestroyDescriptorPool(s->hwctx->act_dev, pl->desc_pool,
2118  s->hwctx->alloc);
2119 
2120  av_freep(&pl->desc_pool_size);
2121  av_freep(&pl->desc_layout);
2122  av_freep(&pl->desc_sets);
2123  av_freep(&pl->desc_set);
2124  av_freep(&pl->desc_bind);
2126  av_freep(&pl->push_consts);
2127  pl->push_consts_num = 0;
2128 }
2129 
2131 {
2132  av_freep(&s->query_props);
2133  av_freep(&s->qf_props);
2134  av_freep(&s->video_props);
2135  av_freep(&s->coop_mat_props);
2136 
2137  av_buffer_unref(&s->device_ref);
2138  av_buffer_unref(&s->frames_ref);
2139 }
2140 
2141 int ff_vk_init(FFVulkanContext *s, void *log_parent,
2142  AVBufferRef *device_ref, AVBufferRef *frames_ref)
2143 {
2144  int err;
2145 
2146  static const AVClass vulkan_context_class = {
2147  .class_name = "vk",
2148  .version = LIBAVUTIL_VERSION_INT,
2149  .parent_log_context_offset = offsetof(FFVulkanContext, log_parent),
2150  };
2151 
2152  memset(s, 0, sizeof(*s));
2153  s->log_parent = log_parent;
2154  s->class = &vulkan_context_class;
2155 
2156  if (frames_ref) {
2157  s->frames_ref = av_buffer_ref(frames_ref);
2158  if (!s->frames_ref)
2159  return AVERROR(ENOMEM);
2160 
2161  s->frames = (AVHWFramesContext *)s->frames_ref->data;
2162  s->hwfc = s->frames->hwctx;
2163 
2164  device_ref = s->frames->device_ref;
2165  }
2166 
2167  s->device_ref = av_buffer_ref(device_ref);
2168  if (!s->device_ref) {
2169  ff_vk_uninit(s);
2170  return AVERROR(ENOMEM);
2171  }
2172 
2173  s->device = (AVHWDeviceContext *)s->device_ref->data;
2174  s->hwctx = s->device->hwctx;
2175 
2176  s->extensions = ff_vk_extensions_to_mask(s->hwctx->enabled_dev_extensions,
2177  s->hwctx->nb_enabled_dev_extensions);
2178 
2179  err = ff_vk_load_functions(s->device, &s->vkfn, s->extensions, 1, 1);
2180  if (err < 0) {
2181  ff_vk_uninit(s);
2182  return err;
2183  }
2184 
2185  err = ff_vk_load_props(s);
2186  if (err < 0) {
2187  ff_vk_uninit(s);
2188  return err;
2189  }
2190 
2191  return 0;
2192 }
vulkan_loader.h
FFVulkanPipeline::bind_point
VkPipelineBindPoint bind_point
Definition: vulkan.h:208
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:899
ff_vk_load_props
int ff_vk_load_props(FFVulkanContext *s)
Loads props/mprops/driver_props.
Definition: vulkan.c:106
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:463
AVPixelFormat
AVPixelFormat
Pixel format.
Definition: pixfmt.h:71
FFVulkanPipeline::desc_pool_size
VkDescriptorPoolSize * desc_pool_size
Definition: vulkan.h:232
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:1908
ImageViewCtx::nb_views
int nb_views
Definition: vulkan.c:1267
ff_vk_pipeline_free
void ff_vk_pipeline_free(FFVulkanContext *s, FFVulkanPipeline *pl)
Definition: vulkan.c:2092
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
FFVulkanPipeline::use_push
int use_push
Definition: vulkan.h:229
ff_comp_identity_map
const VkComponentMapping ff_comp_identity_map
Definition: vulkan.c:27
FFVkExecContext::frame_deps_alloc_size
unsigned int frame_deps_alloc_size
Definition: vulkan.h:142
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:175
AVBufferPool
The buffer pool.
Definition: buffer_internal.h:88
FFVulkanPipeline::pipeline_layout
VkPipelineLayout pipeline_layout
Definition: vulkan.h:211
init_descriptors
static int init_descriptors(FFVulkanContext *s, FFVulkanPipeline *pl)
Definition: vulkan.c:1931
FFVkExecPool::contexts
FFVkExecContext * contexts
Definition: vulkan.h:174
av_pix_fmt_desc_get
const AVPixFmtDescriptor * av_pix_fmt_desc_get(enum AVPixelFormat pix_fmt)
Definition: pixdesc.c:2965
FFVulkanPipeline::nb_desc_pool_size
int nb_desc_pool_size
Definition: vulkan.h:233
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)
Definition: vulkan.c:565
FFVkExecContext::qf
int qf
Definition: vulkan.h:123
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:228
FFVulkanDescriptorSet::aligned_size
VkDeviceSize aligned_size
Definition: vulkan.h:195
ff_vk_exec_get_query
VkResult ff_vk_exec_get_query(FFVulkanContext *s, FFVkExecContext *e, void **data, VkQueryResultFlagBits flags)
Performs nb_queries queries and returns their results and statuses.
Definition: vulkan.c:435
descriptor_props::is_uniform
int is_uniform
Definition: vulkan.c:1500
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:733
av_frame_free
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
Definition: frame.c:162
AVFrame
This structure describes decoded (raw) audio or video data.
Definition: frame.h:389
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:1468
FFVkExecContext::sem_sig_alloc
unsigned int sem_sig_alloc
Definition: vulkan.h:150
FF_VK_EXT_DESCRIPTOR_BUFFER
@ FF_VK_EXT_DESCRIPTOR_BUFFER
Definition: vulkan_functions.h:40
alloc_data_buf
static AVBufferRef * alloc_data_buf(void *opaque, size_t size)
Definition: vulkan.c:1129
data
const char data[16]
Definition: mxf.c:148
high
int high
Definition: dovi_rpuenc.c:38
AV_LOG_VERBOSE
#define AV_LOG_VERBOSE
Detailed information.
Definition: log.h:196
TempSyncCtx::nb_sem
int nb_sem
Definition: vulkan.c:576
FFVkBuffer::address
VkDeviceAddress address
Definition: vulkan.h:100
FFVkExecContext::sem_wait
VkSemaphoreSubmitInfo * sem_wait
Definition: vulkan.h:145
AV_PIX_FMT_BGR24
@ AV_PIX_FMT_BGR24
packed RGB 8:8:8, 24bpp, BGRBGR...
Definition: pixfmt.h:76
AV_PIX_FMT_BGRA
@ AV_PIX_FMT_BGRA
packed BGRA 8:8:8:8, 32bpp, BGRABGRA...
Definition: pixfmt.h:102
ff_vk_init
int ff_vk_init(FFVulkanContext *s, void *log_parent, AVBufferRef *device_ref, AVBufferRef *frames_ref)
Initializes the AVClass, in case this context is not used as the main user's context.
Definition: vulkan.c:2141
ff_vk_uninit
void ff_vk_uninit(FFVulkanContext *s)
Frees main context.
Definition: vulkan.c:2130
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_set_descriptor_buffer
int ff_vk_set_descriptor_buffer(FFVulkanContext *s, FFVulkanPipeline *pl, FFVkExecContext *e, int set, int bind, int elem, FFVkBuffer *buf, VkDeviceSize offset, VkDeviceSize len, VkFormat fmt)
Definition: vulkan.c:1843
FFVulkanPipeline::desc_pool
VkDescriptorPool desc_pool
Definition: vulkan.h:231
ff_vk_shader_set_compute_sizes
void ff_vk_shader_set_compute_sizes(FFVkSPIRVShader *shd, int x, int y, int z)
Definition: vulkan.c:1426
av_popcount
#define av_popcount
Definition: common.h:154
FFVkExecPool::query_pool
VkQueryPool query_pool
Definition: vulkan.h:181
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:663
descriptor_props::type
const char * type
Definition: vulkan.c:1499
AVFrame::data
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition: frame.h:410
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:118
ImageViewCtx
Definition: vulkan.c:1266
FFVkExecContext::frame_update_alloc_size
unsigned int frame_update_alloc_size
Definition: vulkan.h:170
av_pix_fmt_count_planes
int av_pix_fmt_count_planes(enum AVPixelFormat pix_fmt)
Definition: pixdesc.c:3005
ff_vk_add_push_constant
int ff_vk_add_push_constant(FFVulkanPipeline *pl, int offset, int size, VkShaderStageFlagBits stage)
Add/update push constants for execution.
Definition: vulkan.c:1194
AVVkFrame::img
VkImage img[AV_NUM_DATA_POINTERS]
Vulkan images to which the memory is bound to.
Definition: hwcontext_vulkan.h:307
destroy_avvkbuf
static void destroy_avvkbuf(void *opaque, uint8_t *data)
Definition: vulkan.c:986
ff_vk_find_struct
static const void * ff_vk_find_struct(const void *chain, VkStructureType stype)
Definition: vulkan.h:292
fail
#define fail()
Definition: checkasm.h:188
ff_vk_exec_add_dep_bool_sem
int ff_vk_exec_add_dep_bool_sem(FFVulkanContext *s, FFVkExecContext *e, VkSemaphore *sem, int nb, VkPipelineStageFlagBits2 stage, int wait)
Definition: vulkan.c:592
FFVulkanPipeline::wg_size
int wg_size[3]
Definition: vulkan.h:219
ff_vk_unmap_buffers
int ff_vk_unmap_buffers(FFVulkanContext *s, FFVkBuffer **buf, int nb_buffers, int flush)
Definition: vulkan.c:1068
AVVulkanFramesContext
Allocated as AVHWFramesContext.hwctx, used to set pool-specific options.
Definition: hwcontext_vulkan.h:213
FFVulkanPipeline::pipeline
VkPipeline pipeline
Definition: vulkan.h:212
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:185
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:35
FF_VK_EXT_COOP_MATRIX
@ FF_VK_EXT_COOP_MATRIX
Definition: vulkan_functions.h:48
FFVkExecPool::query_statuses
int query_statuses
Definition: vulkan.h:184
descriptor_props::struct_size
size_t struct_size
Definition: vulkan.c:1498
AVHWDeviceContext
This struct aggregates all the (hardware/vendor-specific) "high-level" state, i.e.
Definition: hwcontext.h:60
FFVulkanDescriptorSet::binding
VkDescriptorSetLayoutBinding * binding
Definition: vulkan.h:199
FFVulkanPipeline::desc_sets
VkDescriptorSet * desc_sets
Definition: vulkan.h:230
avassert.h
FFVulkanPipeline::nb_descriptor_sets
int nb_descriptor_sets
Definition: vulkan.h:226
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:141
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:994
FFVkExecContext::queue_family_dst
uint32_t * queue_family_dst
Definition: vulkan.h:166
av_buffer_pool_get
AVBufferRef * av_buffer_pool_get(AVBufferPool *pool)
Allocate a new AVBuffer, reusing an old buffer from the pool when available.
Definition: buffer.c:390
av_fast_realloc
void * av_fast_realloc(void *ptr, unsigned int *size, size_t min_size)
Reallocate the given buffer if it is not large enough, otherwise do nothing.
Definition: mem.c:497
FFVulkanPipeline::assoc_pool
FFVkExecPool * assoc_pool
Definition: vulkan.h:235
s
#define s(width, name)
Definition: cbs_vp9.c:198
FF_VK_EXT_PUSH_DESCRIPTOR
@ FF_VK_EXT_PUSH_DESCRIPTOR
Definition: vulkan_functions.h:51
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:752
offsets
static const int offsets[]
Definition: hevc_pel.c:34
av_realloc_array
void * av_realloc_array(void *ptr, size_t nmemb, size_t size)
Definition: mem.c:217
ff_vk_load_functions
static int ff_vk_load_functions(AVHWDeviceContext *ctx, FFVulkanFunctions *vk, uint64_t extensions_mask, int has_inst, int has_dev)
Function loader.
Definition: vulkan_loader.h:98
pix_fmt
static enum AVPixelFormat pix_fmt
Definition: demux_decode.c:41
FFVkExecContext::fence
VkFence fence
Definition: vulkan.h:130
ff_vk_exec_wait
void ff_vk_exec_wait(FFVulkanContext *s, FFVkExecContext *e)
Definition: vulkan.c:470
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:1778
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:137
ctx
AVFormatContext * ctx
Definition: movenc.c:49
av_frame_clone
AVFrame * av_frame_clone(const AVFrame *src)
Create a new frame that references the same data as src.
Definition: frame.c:597
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:541
ff_vk_unmap_buffer
static int ff_vk_unmap_buffer(FFVulkanContext *s, FFVkBuffer *buf, int flush)
Definition: vulkan.h:452
ff_vk_exec_bind_pipeline
void ff_vk_exec_bind_pipeline(FFVulkanContext *s, FFVkExecContext *e, FFVulkanPipeline *pl)
Definition: vulkan.c:2063
ff_vk_exec_pool_free
void ff_vk_exec_pool_free(FFVulkanContext *s, FFVkExecPool *pool)
Definition: vulkan.c:238
ImageViewCtx::views
VkImageView views[]
Definition: vulkan.c:1268
FFVkExecContext::frame_update
uint8_t * frame_update
Definition: vulkan.h:169
FFVkExecContext::query_idx
int query_idx
Definition: vulkan.h:133
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:186
FFVkExecContext::parent
const struct FFVkExecPool * parent
Definition: vulkan.h:117
if
if(ret)
Definition: filter_design.txt:179
AV_PIX_FMT_RGBA64
#define AV_PIX_FMT_RGBA64
Definition: pixfmt.h:468
LIBAVUTIL_VERSION_INT
#define LIBAVUTIL_VERSION_INT
Definition: version.h:85
AVClass
Describe the class of an AVClass context structure.
Definition: log.h:66
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:844
FFVkExecContext::sem_sig_val_dst_alloc
unsigned int sem_sig_val_dst_alloc
Definition: vulkan.h:154
descriptor_props::mem_quali
int mem_quali
Definition: vulkan.c:1501
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:161
FFVulkanDescriptorSet::singular
int singular
Definition: vulkan.h:204
FFVkExecContext::sem_sig_cnt
int sem_sig_cnt
Definition: vulkan.h:151
TempSyncCtx::sem
VkSemaphore sem[]
Definition: vulkan.c:577
load_enabled_qfs
static void load_enabled_qfs(FFVulkanContext *s)
Definition: vulkan.c:87
TempSyncCtx
Definition: vulkan.c:575
flush
void(* flush)(AVBSFContext *ctx)
Definition: dts2pts.c:370
FFVkExecContext::qi
int qi
Definition: vulkan.h:124
FFVkExecContext::had_submission
int had_submission
Definition: vulkan.h:119
FFVkBuffer::size
size_t size
Definition: vulkan.h:99
descriptor_props::dim_needed
int dim_needed
Definition: vulkan.c:1502
FFVkExecPool::nb_queries
int nb_queries
Definition: vulkan.h:187
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:2021
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:278
FFVkBuffer::mapped_mem
uint8_t * mapped_mem
Definition: vulkan.h:107
FFVulkanContext
Definition: vulkan.h:238
ff_vk_count_images
static int ff_vk_count_images(AVVkFrame *f)
Definition: vulkan.h:283
AV_PIX_FMT_ABGR
@ AV_PIX_FMT_ABGR
packed ABGR 8:8:8:8, 32bpp, ABGRABGR...
Definition: pixfmt.h:101
FFVulkanPipeline
Definition: vulkan.h:207
index
int index
Definition: gxfenc.c:90
FFVkExecContext::query_data
void * query_data
Definition: vulkan.h:132
ff_vk_shader_print
void ff_vk_shader_print(void *ctx, FFVkSPIRVShader *shd, int prio)
Definition: vulkan.c:1437
pthread_mutex_unlock
#define pthread_mutex_unlock(a)
Definition: ffprobe.c:82
av_buffer_create
AVBufferRef * av_buffer_create(uint8_t *data, size_t size, void(*free)(void *opaque, uint8_t *data), void *opaque, int flags)
Create an AVBuffer from an existing array.
Definition: buffer.c:55
update_set_pool_write
static void update_set_pool_write(FFVulkanContext *s, FFVulkanPipeline *pl, FFVkExecContext *e, FFVulkanDescriptorSet *desc_set, int set, VkWriteDescriptorSet *write_info)
Definition: vulkan.c:1752
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:1400
usage
const char * usage
Definition: floatimg_cmp.c:60
AV_PIX_FMT_X2BGR10
#define AV_PIX_FMT_X2BGR10
Definition: pixfmt.h:537
f
f
Definition: af_crystalizer.c:122
FFVkExecContext::layout_dst
VkImageLayout * layout_dst
Definition: vulkan.h:163
destroy_imageviews
static void destroy_imageviews(void *opaque, uint8_t *data)
Definition: vulkan.c:1271
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:167
AVVkFrame::access
VkAccessFlagBits access[AV_NUM_DATA_POINTERS]
Updated after every barrier.
Definition: hwcontext_vulkan.h:331
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
dst
uint8_t ptrdiff_t const uint8_t ptrdiff_t int intptr_t intptr_t int int16_t * dst
Definition: dsp.h:83
AVVkFrame
Definition: hwcontext_vulkan.h:302
for
for(k=2;k<=8;++k)
Definition: h264pred_template.c:425
print
static void print(AVTreeNode *t, int depth)
Definition: tree.c:45
AV_PIX_FMT_RGB48
#define AV_PIX_FMT_RGB48
Definition: pixfmt.h:464
size
int size
Definition: twinvq_data.h:10344
AV_NUM_DATA_POINTERS
#define AV_NUM_DATA_POINTERS
Definition: frame.h:390
FFVkExecContext::nb_frame_deps
int nb_frame_deps
Definition: vulkan.h:143
FFVkQueueFamilyCtx
Definition: vulkan.h:110
FFVkExecContext::sem_sig_val_dst_cnt
int sem_sig_val_dst_cnt
Definition: vulkan.h:155
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:366
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:115
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:1921
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:1246
destroy_tmp_semaphores
static void destroy_tmp_semaphores(void *opaque, uint8_t *data)
Definition: vulkan.c:580
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:147
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:122
descriptor_props
Definition: vulkan.c:1497
ff_vk_exec_start
int ff_vk_exec_start(FFVulkanContext *s, FFVkExecContext *e)
Start/submit/wait an execution.
Definition: vulkan.c:479
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:256
FFVulkanPipeline::push_consts
VkPushConstantRange * push_consts
Definition: vulkan.h:215
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:1357
FFVkExecContext::layout_dst_alloc
unsigned int layout_dst_alloc
Definition: vulkan.h:164
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:1259
FFMIN
#define FFMIN(a, b)
Definition: macros.h:49
FFVkBuffer::mem
VkDeviceMemory mem
Definition: vulkan.h:97
AV_PIX_FMT_X2RGB10
#define AV_PIX_FMT_X2RGB10
Definition: pixfmt.h:536
av_mallocz
void * av_mallocz(size_t size)
Allocate a memory block with alignment suitable for all memory accesses (including vectors if availab...
Definition: mem.c:256
FFVkSPIRVShader::src
AVBPrint src
Definition: vulkan.h:77
vk_qf_get_index
static int vk_qf_get_index(FFVulkanContext *s, VkQueueFlagBits dev_family, int *nb)
Definition: vulkan.c:216
FFVkExecContext::frame_locked_alloc_size
unsigned int frame_locked_alloc_size
Definition: vulkan.h:158
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:40
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:1106
av_calloc
void * av_calloc(size_t nmemb, size_t size)
Definition: mem.c:264
AV_PIX_FMT_RGB565
#define AV_PIX_FMT_RGB565
Definition: pixfmt.h:465
FFVkExecContext::sem_wait_alloc
unsigned int sem_wait_alloc
Definition: vulkan.h:146
AVVkFrame::sem
VkSemaphore sem[AV_NUM_DATA_POINTERS]
Synchronization timeline semaphores, one for each VkImage.
Definition: hwcontext_vulkan.h:340
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:216
ff_vk_pipeline_descriptor_set_add
int ff_vk_pipeline_descriptor_set_add(FFVulkanContext *s, FFVulkanPipeline *pl, FFVkSPIRVShader *shd, FFVulkanDescriptorSetBinding *desc, int nb, int singular, int print_to_shader_only)
Add descriptor to a pipeline.
Definition: vulkan.c:1518
ret
ret
Definition: filter_design.txt:187
pixfmt
enum AVPixelFormat pixfmt
Definition: kmsgrab.c:367
AV_PIX_FMT_0BGR
@ AV_PIX_FMT_0BGR
packed BGR 8:8:8, 32bpp, XBGRXBGR... X=unused/undefined
Definition: pixfmt.h:264
ff_vk_map_buffer
static int ff_vk_map_buffer(FFVulkanContext *s, FFVkBuffer *buf, uint8_t **mem, int invalidate)
Definition: vulkan.h:445
AVClass::class_name
const char * class_name
The name of the class; usually it is the same name as the context structure type to which the AVClass...
Definition: log.h:71
AVHWFramesContext::hwctx
void * hwctx
The format-specific data, allocated and freed automatically along with this context.
Definition: hwcontext.h:150
FFVkExecPool
Definition: vulkan.h:173
FFVkExecContext::frame_locked
uint8_t * frame_locked
Definition: vulkan.h:157
FFVkExecPool::query_data
void * query_data
Definition: vulkan.h:182
descriptor_props::buf_content
int buf_content
Definition: vulkan.c:1503
FFVkExecContext::sem_sig
VkSemaphoreSubmitInfo * sem_sig
Definition: vulkan.h:149
av_bprintf
void av_bprintf(AVBPrint *buf, const char *fmt,...)
Definition: bprint.c:99
FFVkExecContext::buf
VkCommandBuffer buf
Definition: vulkan.h:127
SIZE_SPECIFIER
#define SIZE_SPECIFIER
Definition: internal.h:129
GLSLA
#define GLSLA(...)
Definition: vulkan.h:49
FFVkQueueFamilyCtx::nb_queues
int nb_queues
Definition: vulkan.h:112
free_data_buf
static void free_data_buf(void *opaque, uint8_t *data)
Definition: vulkan.c:1121
FFVkSPIRVShader
Definition: vulkan.h:75
FFVulkanPipeline::desc_set
FFVulkanDescriptorSet * desc_set
Definition: vulkan.h:223
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:1995
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:348
desc
const char * desc
Definition: libsvtav1.c:79
GLSLC
#define GLSLC(N, S)
Definition: vulkan.h:44
mem.h
AVVkFrame::layout
VkImageLayout layout[AV_NUM_DATA_POINTERS]
Definition: hwcontext_vulkan.h:332
AVBufferRef
A reference to a data buffer.
Definition: buffer.h:82
FFVkExecPool::cmd_bufs
VkCommandBuffer * cmd_bufs
Definition: vulkan.h:178
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:515
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:1214
av_freep
#define av_freep(p)
Definition: tableprint_vlc.h:34
FFVkExecContext::buf_deps_alloc_size
unsigned int buf_deps_alloc_size
Definition: vulkan.h:138
FFVkExecContext::buf_deps
AVBufferRef ** buf_deps
Definition: vulkan.h:136
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:1630
ff_vk_exec_submit
int ff_vk_exec_submit(FFVulkanContext *s, FFVkExecContext *e)
Definition: vulkan.c:778
flags
#define flags(name, subs,...)
Definition: cbs_av1.c:482
ff_vk_extensions_to_mask
static uint64_t ff_vk_extensions_to_mask(const char *const *extensions, int nb_extensions)
Definition: vulkan_loader.h:36
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:27
FFVkExecPool::qd_size
size_t qd_size
Definition: vulkan.h:188
FFVulkanDescriptorSet
Definition: vulkan.h:191
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:1283
FFVulkanPipeline::desc_bind
VkDescriptorBufferBindingInfoEXT * desc_bind
Definition: vulkan.h:224
ff_vk_shader_free
void ff_vk_shader_free(FFVulkanContext *s, FFVkSPIRVShader *shd)
Definition: vulkan.c:1459
FFVkExecPool::query_results
int query_results
Definition: vulkan.h:183
FFVkExecContext::sem_sig_val_dst
uint64_t ** sem_sig_val_dst
Definition: vulkan.h:153
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)
FFVulkanPipeline::desc_layout
VkDescriptorSetLayout * desc_layout
Definition: vulkan.h:222
FFVulkanFunctions
Definition: vulkan_functions.h:255
FFVkExecPool::pool_size
int pool_size
Definition: vulkan.h:179
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:1736
skip
static void BS_FUNC() skip(BSCTX *bc, unsigned int n)
Skip n bits in the buffer.
Definition: bitstream_template.h:375
FFVkExecPool::cmd_buf_pool
VkCommandPool cmd_buf_pool
Definition: vulkan.h:177
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:1142
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:1021
FFVkExecContext::idx
uint32_t idx
Definition: vulkan.h:116
src
#define src
Definition: vp8dsp.c:248
FFVulkanPipeline::bound_buffer_indices
uint32_t * bound_buffer_indices
Definition: vulkan.h:225
FFVkQueueFamilyCtx::queue_family
int queue_family
Definition: vulkan.h:111
pthread_mutex_lock
#define pthread_mutex_lock(a)
Definition: ffprobe.c:78
FFVkExecContext::access_dst
VkAccessFlagBits * access_dst
Definition: vulkan.h:160