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  /* Free shader-specific data */
266  for (int i = 0; i < pool->nb_reg_shd; i++) {
267  FFVulkanShaderData *sd = &pool->reg_shd[i];
268 
269  if (s->extensions & FF_VK_EXT_DESCRIPTOR_BUFFER) {
270  for (int j = 0; j < sd->nb_descriptor_sets; j++) {
271  FFVulkanDescriptorSetData *set_data = &sd->desc_set_buf[j];
272  if (set_data->buf.mem)
273  ff_vk_unmap_buffer(s, &set_data->buf, 0);
274  ff_vk_free_buf(s, &set_data->buf);
275  }
276  }
277 
278  if (sd->desc_pool)
279  vk->DestroyDescriptorPool(s->hwctx->act_dev, sd->desc_pool,
280  s->hwctx->alloc);
281 
282  av_freep(&sd->desc_set_buf);
283  av_freep(&sd->desc_bind);
284  av_freep(&sd->desc_sets);
285  }
286 
287  if (pool->cmd_bufs)
288  vk->FreeCommandBuffers(s->hwctx->act_dev, pool->cmd_buf_pool,
289  pool->pool_size, pool->cmd_bufs);
290  if (pool->cmd_buf_pool)
291  vk->DestroyCommandPool(s->hwctx->act_dev, pool->cmd_buf_pool, s->hwctx->alloc);
292  if (pool->query_pool)
293  vk->DestroyQueryPool(s->hwctx->act_dev, pool->query_pool, s->hwctx->alloc);
294 
295  av_free(pool->query_data);
296  av_free(pool->cmd_bufs);
297  av_free(pool->contexts);
298 }
299 
301  FFVkExecPool *pool, int nb_contexts,
302  int nb_queries, VkQueryType query_type, int query_64bit,
303  const void *query_create_pnext)
304 {
305  int err;
306  VkResult ret;
307  FFVulkanFunctions *vk = &s->vkfn;
308 
309  VkCommandPoolCreateInfo cqueue_create;
310  VkCommandBufferAllocateInfo cbuf_create;
311 
312  const VkQueryPoolVideoEncodeFeedbackCreateInfoKHR *ef = NULL;
313 
314  if (query_type == VK_QUERY_TYPE_VIDEO_ENCODE_FEEDBACK_KHR) {
315  ef = ff_vk_find_struct(query_create_pnext,
316  VK_STRUCTURE_TYPE_QUERY_POOL_VIDEO_ENCODE_FEEDBACK_CREATE_INFO_KHR);
317  if (!ef)
318  return AVERROR(EINVAL);
319  }
320 
321  /* Create command pool */
322  cqueue_create = (VkCommandPoolCreateInfo) {
323  .sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
324  .flags = VK_COMMAND_POOL_CREATE_TRANSIENT_BIT |
325  VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,
326  .queueFamilyIndex = qf->queue_family,
327  };
328  ret = vk->CreateCommandPool(s->hwctx->act_dev, &cqueue_create,
329  s->hwctx->alloc, &pool->cmd_buf_pool);
330  if (ret != VK_SUCCESS) {
331  av_log(s, AV_LOG_ERROR, "Command pool creation failure: %s\n",
332  ff_vk_ret2str(ret));
333  err = AVERROR_EXTERNAL;
334  goto fail;
335  }
336 
337  /* Allocate space for command buffers */
338  pool->cmd_bufs = av_malloc(nb_contexts*sizeof(*pool->cmd_bufs));
339  if (!pool->cmd_bufs) {
340  err = AVERROR(ENOMEM);
341  goto fail;
342  }
343 
344  /* Allocate command buffer */
345  cbuf_create = (VkCommandBufferAllocateInfo) {
346  .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
347  .level = VK_COMMAND_BUFFER_LEVEL_PRIMARY,
348  .commandPool = pool->cmd_buf_pool,
349  .commandBufferCount = nb_contexts,
350  };
351  ret = vk->AllocateCommandBuffers(s->hwctx->act_dev, &cbuf_create,
352  pool->cmd_bufs);
353  if (ret != VK_SUCCESS) {
354  av_log(s, AV_LOG_ERROR, "Command buffer alloc failure: %s\n",
355  ff_vk_ret2str(ret));
356  err = AVERROR_EXTERNAL;
357  goto fail;
358  }
359 
360  /* Query pool */
361  if (nb_queries) {
362  VkQueryPoolCreateInfo query_pool_info = {
363  .sType = VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO,
364  .pNext = query_create_pnext,
365  .queryType = query_type,
366  .queryCount = nb_queries*nb_contexts,
367  };
368  ret = vk->CreateQueryPool(s->hwctx->act_dev, &query_pool_info,
369  s->hwctx->alloc, &pool->query_pool);
370  if (ret != VK_SUCCESS) {
371  av_log(s, AV_LOG_ERROR, "Query pool alloc failure: %s\n",
372  ff_vk_ret2str(ret));
373  err = AVERROR_EXTERNAL;
374  goto fail;
375  }
376 
377  pool->nb_queries = nb_queries;
378  pool->query_status_stride = 1 + 1; /* One result, one status by default */
379  pool->query_results = nb_queries;
380  pool->query_statuses = nb_queries;
381 
382  /* Video encode quieries produce two results per query */
383  if (query_type == VK_QUERY_TYPE_VIDEO_ENCODE_FEEDBACK_KHR) {
384  int nb_results = av_popcount(ef->encodeFeedbackFlags);
385  pool->query_status_stride = nb_results + 1;
386  pool->query_results *= nb_results;
387  } else if (query_type == VK_QUERY_TYPE_RESULT_STATUS_ONLY_KHR) {
388  pool->query_status_stride = 1;
389  pool->query_results = 0;
390  }
391 
392  pool->qd_size = (pool->query_results + pool->query_statuses)*(query_64bit ? 8 : 4);
393 
394  /* Allocate space for the query data */
395  pool->query_data = av_calloc(nb_contexts, pool->qd_size);
396  if (!pool->query_data) {
397  err = AVERROR(ENOMEM);
398  goto fail;
399  }
400  }
401 
402  /* Allocate space for the contexts */
403  pool->contexts = av_calloc(nb_contexts, sizeof(*pool->contexts));
404  if (!pool->contexts) {
405  err = AVERROR(ENOMEM);
406  goto fail;
407  }
408 
409  pool->pool_size = nb_contexts;
410 
411  /* Init contexts */
412  for (int i = 0; i < pool->pool_size; i++) {
413  FFVkExecContext *e = &pool->contexts[i];
414  VkFenceCreateInfo fence_create = {
415  .sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,
416  .flags = VK_FENCE_CREATE_SIGNALED_BIT,
417  };
418 
419  /* Mutex */
420  err = pthread_mutex_init(&e->lock, NULL);
421  if (err != 0)
422  return AVERROR(err);
423 
424  /* Fence */
425  ret = vk->CreateFence(s->hwctx->act_dev, &fence_create, s->hwctx->alloc,
426  &e->fence);
427  if (ret != VK_SUCCESS) {
428  av_log(s, AV_LOG_ERROR, "Failed to create submission fence: %s\n",
429  ff_vk_ret2str(ret));
430  return AVERROR_EXTERNAL;
431  }
432 
433  e->idx = i;
434  e->parent = pool;
435 
436  /* Query data */
437  e->query_data = ((uint8_t *)pool->query_data) + pool->qd_size*i;
438  e->query_idx = nb_queries*i;
439 
440  /* Command buffer */
441  e->buf = pool->cmd_bufs[i];
442 
443  /* Queue index distribution */
444  e->qi = i % qf->nb_queues;
445  e->qf = qf->queue_family;
446  vk->GetDeviceQueue(s->hwctx->act_dev, qf->queue_family,
447  e->qi, &e->queue);
448  }
449 
450  return 0;
451 
452 fail:
453  ff_vk_exec_pool_free(s, pool);
454  return err;
455 }
456 
458  void **data, VkQueryResultFlagBits flags)
459 {
460  FFVulkanFunctions *vk = &s->vkfn;
461  const FFVkExecPool *pool = e->parent;
462  VkQueryResultFlags qf = flags & ~(VK_QUERY_RESULT_64_BIT |
463  VK_QUERY_RESULT_WITH_STATUS_BIT_KHR);
464 
465  if (!e->query_data) {
466  av_log(s, AV_LOG_ERROR, "Requested a query with a NULL query_data pointer!\n");
467  return VK_INCOMPLETE;
468  }
469 
470  qf |= pool->query_64bit ?
471  VK_QUERY_RESULT_64_BIT : 0x0;
472  qf |= pool->query_statuses ?
473  VK_QUERY_RESULT_WITH_STATUS_BIT_KHR : 0x0;
474 
475  if (data)
476  *data = e->query_data;
477 
478  return vk->GetQueryPoolResults(s->hwctx->act_dev, pool->query_pool,
479  e->query_idx,
480  pool->nb_queries,
481  pool->qd_size, e->query_data,
482  pool->qd_size, qf);
483 }
484 
486 {
487  FFVulkanFunctions *vk = &s->vkfn;
488  FFVkExecContext *e = &pool->contexts[pool->idx];
489 
490  /* Check if last submission has already finished.
491  * If so, don't waste resources and reuse the same buffer. */
492  if (vk->GetFenceStatus(s->hwctx->act_dev, e->fence) == VK_SUCCESS)
493  return e;
494 
495  pool->idx = (pool->idx + 1) % pool->pool_size;
496  return &pool->contexts[pool->idx];
497 }
498 
500 {
501  FFVulkanFunctions *vk = &s->vkfn;
503  vk->WaitForFences(s->hwctx->act_dev, 1, &e->fence, VK_TRUE, UINT64_MAX);
506 }
507 
509 {
510  VkResult ret;
511  FFVulkanFunctions *vk = &s->vkfn;
512  const FFVkExecPool *pool = e->parent;
513 
514  VkCommandBufferBeginInfo cmd_start = {
515  .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
516  .flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,
517  };
518 
519  /* Wait for the fence to be signalled */
520  vk->WaitForFences(s->hwctx->act_dev, 1, &e->fence, VK_TRUE, UINT64_MAX);
521 
522  /* vkResetFences is defined as being host-synchronized */
524  vk->ResetFences(s->hwctx->act_dev, 1, &e->fence);
526 
527  /* Discard queue dependencies */
529 
530  ret = vk->BeginCommandBuffer(e->buf, &cmd_start);
531  if (ret != VK_SUCCESS) {
532  av_log(s, AV_LOG_ERROR, "Failed to start command recoding: %s\n",
533  ff_vk_ret2str(ret));
534  return AVERROR_EXTERNAL;
535  }
536 
537  if (pool->nb_queries)
538  vk->CmdResetQueryPool(e->buf, pool->query_pool,
539  e->query_idx, pool->nb_queries);
540 
541  return 0;
542 }
543 
545 {
546  for (int j = 0; j < e->nb_buf_deps; j++)
547  av_buffer_unref(&e->buf_deps[j]);
548  e->nb_buf_deps = 0;
549 
550  for (int j = 0; j < e->nb_frame_deps; j++) {
551  AVFrame *f = e->frame_deps[j];
552  if (e->frame_locked[j]) {
553  AVHWFramesContext *hwfc = (AVHWFramesContext *)f->hw_frames_ctx->data;
554  AVVulkanFramesContext *vkfc = hwfc->hwctx;
555  AVVkFrame *vkf = (AVVkFrame *)f->data[0];
556  vkfc->unlock_frame(hwfc, vkf);
557  e->frame_locked[j] = 0;
558  }
559  e->frame_update[j] = 0;
560  if (f->buf[0])
561  av_frame_free(&e->frame_deps[j]);
562  }
563  e->nb_frame_deps = 0;
564 
565  e->sem_wait_cnt = 0;
566  e->sem_sig_cnt = 0;
567  e->sem_sig_val_dst_cnt = 0;
568 }
569 
571  AVBufferRef **deps, int nb_deps, int ref)
572 {
574  (e->nb_buf_deps + nb_deps) * sizeof(*dst));
575  if (!dst) {
577  return AVERROR(ENOMEM);
578  }
579 
580  e->buf_deps = dst;
581 
582  for (int i = 0; i < nb_deps; i++) {
583  e->buf_deps[e->nb_buf_deps] = ref ? av_buffer_ref(deps[i]) : deps[i];
584  if (!e->buf_deps[e->nb_buf_deps]) {
586  return AVERROR(ENOMEM);
587  }
588  e->nb_buf_deps++;
589  }
590 
591  return 0;
592 }
593 
594 #define ARR_REALLOC(str, arr, alloc_s, cnt) \
595  do { \
596  arr = av_fast_realloc(str->arr, alloc_s, (cnt + 1)*sizeof(*arr)); \
597  if (!arr) { \
598  ff_vk_exec_discard_deps(s, e); \
599  return AVERROR(ENOMEM); \
600  } \
601  str->arr = arr; \
602  } while (0)
603 
604 typedef struct TempSyncCtx {
605  int nb_sem;
606  VkSemaphore sem[];
607 } TempSyncCtx;
608 
609 static void destroy_tmp_semaphores(void *opaque, uint8_t *data)
610 {
611  FFVulkanContext *s = opaque;
612  FFVulkanFunctions *vk = &s->vkfn;
613  TempSyncCtx *ts = (TempSyncCtx *)data;
614 
615  for (int i = 0; i < ts->nb_sem; i++)
616  vk->DestroySemaphore(s->hwctx->act_dev, ts->sem[i], s->hwctx->alloc);
617 
618  av_free(ts);
619 }
620 
622  VkSemaphore *sem, int nb,
623  VkPipelineStageFlagBits2 stage,
624  int wait)
625 {
626  int err;
627  size_t buf_size;
628  AVBufferRef *buf;
629  TempSyncCtx *ts;
630  FFVulkanFunctions *vk = &s->vkfn;
631 
632  /* Do not transfer ownership if we're signalling a binary semaphore,
633  * since we're probably exporting it. */
634  if (!wait) {
635  for (int i = 0; i < nb; i++) {
636  VkSemaphoreSubmitInfo *sem_sig;
637  ARR_REALLOC(e, sem_sig, &e->sem_sig_alloc, e->sem_sig_cnt);
638 
639  e->sem_sig[e->sem_sig_cnt++] = (VkSemaphoreSubmitInfo) {
640  .sType = VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO,
641  .semaphore = sem[i],
642  .stageMask = stage,
643  };
644  }
645 
646  return 0;
647  }
648 
649  buf_size = sizeof(int) + sizeof(VkSemaphore)*nb;
650  ts = av_mallocz(buf_size);
651  if (!ts) {
652  err = AVERROR(ENOMEM);
653  goto fail;
654  }
655 
656  memcpy(ts->sem, sem, nb*sizeof(*sem));
657  ts->nb_sem = nb;
658 
659  buf = av_buffer_create((uint8_t *)ts, buf_size, destroy_tmp_semaphores, s, 0);
660  if (!buf) {
661  av_free(ts);
662  err = AVERROR(ENOMEM);
663  goto fail;
664  }
665 
666  err = ff_vk_exec_add_dep_buf(s, e, &buf, 1, 0);
667  if (err < 0) {
668  av_buffer_unref(&buf);
669  return err;
670  }
671 
672  for (int i = 0; i < nb; i++) {
673  VkSemaphoreSubmitInfo *sem_wait;
675 
676  e->sem_wait[e->sem_wait_cnt++] = (VkSemaphoreSubmitInfo) {
677  .sType = VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO,
678  .semaphore = sem[i],
679  .stageMask = stage,
680  };
681  }
682 
683  return 0;
684 
685 fail:
686  for (int i = 0; i < nb; i++)
687  vk->DestroySemaphore(s->hwctx->act_dev, sem[i], s->hwctx->alloc);
688 
689  return err;
690 }
691 
693  VkPipelineStageFlagBits2 wait_stage,
694  VkPipelineStageFlagBits2 signal_stage)
695 {
696  uint8_t *frame_locked;
697  uint8_t *frame_update;
698  AVFrame **frame_deps;
699  VkImageLayout *layout_dst;
700  uint32_t *queue_family_dst;
701  VkAccessFlagBits *access_dst;
702 
703  AVHWFramesContext *hwfc = (AVHWFramesContext *)f->hw_frames_ctx->data;
704  AVVulkanFramesContext *vkfc = hwfc->hwctx;
705  AVVkFrame *vkf = (AVVkFrame *)f->data[0];
706  int nb_images = ff_vk_count_images(vkf);
707 
708  /* Don't add duplicates */
709  for (int i = 0; i < e->nb_frame_deps; i++)
710  if (e->frame_deps[i]->data[0] == f->data[0])
711  return 1;
712 
713  ARR_REALLOC(e, layout_dst, &e->layout_dst_alloc, e->nb_frame_deps);
714  ARR_REALLOC(e, queue_family_dst, &e->queue_family_dst_alloc, e->nb_frame_deps);
715  ARR_REALLOC(e, access_dst, &e->access_dst_alloc, e->nb_frame_deps);
716 
717  ARR_REALLOC(e, frame_locked, &e->frame_locked_alloc_size, e->nb_frame_deps);
718  ARR_REALLOC(e, frame_update, &e->frame_update_alloc_size, e->nb_frame_deps);
719  ARR_REALLOC(e, frame_deps, &e->frame_deps_alloc_size, e->nb_frame_deps);
720 
721  e->frame_deps[e->nb_frame_deps] = f->buf[0] ? av_frame_clone(f) : f;
722  if (!e->frame_deps[e->nb_frame_deps]) {
724  return AVERROR(ENOMEM);
725  }
726 
727  vkfc->lock_frame(hwfc, vkf);
728  e->frame_locked[e->nb_frame_deps] = 1;
729  e->frame_update[e->nb_frame_deps] = 0;
730  e->nb_frame_deps++;
731 
732  for (int i = 0; i < nb_images; i++) {
733  VkSemaphoreSubmitInfo *sem_wait;
734  VkSemaphoreSubmitInfo *sem_sig;
735  uint64_t **sem_sig_val_dst;
736 
738  ARR_REALLOC(e, sem_sig, &e->sem_sig_alloc, e->sem_sig_cnt);
739  ARR_REALLOC(e, sem_sig_val_dst, &e->sem_sig_val_dst_alloc, e->sem_sig_val_dst_cnt);
740 
741  e->sem_wait[e->sem_wait_cnt++] = (VkSemaphoreSubmitInfo) {
742  .sType = VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO,
743  .semaphore = vkf->sem[i],
744  .value = vkf->sem_value[i],
745  .stageMask = wait_stage,
746  };
747 
748  e->sem_sig[e->sem_sig_cnt++] = (VkSemaphoreSubmitInfo) {
749  .sType = VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO,
750  .semaphore = vkf->sem[i],
751  .value = vkf->sem_value[i] + 1,
752  .stageMask = signal_stage,
753  };
754 
755  e->sem_sig_val_dst[e->sem_sig_val_dst_cnt] = &vkf->sem_value[i];
756  e->sem_sig_val_dst_cnt++;
757  }
758 
759  return 0;
760 }
761 
763  VkImageMemoryBarrier2 *bar, uint32_t *nb_img_bar)
764 {
765  int i;
766  for (i = 0; i < e->nb_frame_deps; i++)
767  if (e->frame_deps[i]->data[0] == f->data[0])
768  break;
769  av_assert0(i < e->nb_frame_deps);
770 
771  /* Don't update duplicates */
772  if (nb_img_bar && !e->frame_update[i])
773  (*nb_img_bar)++;
774 
775  e->queue_family_dst[i] = bar->dstQueueFamilyIndex;
776  e->access_dst[i] = bar->dstAccessMask;
777  e->layout_dst[i] = bar->newLayout;
778  e->frame_update[i] = 1;
779 }
780 
782  VkSemaphore *dst, uint64_t *dst_val,
783  AVFrame *f)
784 {
785  uint64_t **sem_sig_val_dst;
786  AVVkFrame *vkf = (AVVkFrame *)f->data[0];
787 
788  /* Reject unknown frames */
789  int i;
790  for (i = 0; i < e->nb_frame_deps; i++)
791  if (e->frame_deps[i]->data[0] == f->data[0])
792  break;
793  if (i == e->nb_frame_deps)
794  return AVERROR(EINVAL);
795 
796  ARR_REALLOC(e, sem_sig_val_dst, &e->sem_sig_val_dst_alloc, e->sem_sig_val_dst_cnt);
797 
798  *dst = vkf->sem[0];
799  *dst_val = vkf->sem_value[0];
800 
801  e->sem_sig_val_dst[e->sem_sig_val_dst_cnt] = dst_val;
802  e->sem_sig_val_dst_cnt++;
803 
804  return 0;
805 }
806 
808 {
809  VkResult ret;
810  FFVulkanFunctions *vk = &s->vkfn;
811  VkCommandBufferSubmitInfo cmd_buf_info = (VkCommandBufferSubmitInfo) {
812  .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_SUBMIT_INFO,
813  .commandBuffer = e->buf,
814  };
815  VkSubmitInfo2 submit_info = (VkSubmitInfo2) {
816  .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO_2,
817  .pCommandBufferInfos = &cmd_buf_info,
818  .commandBufferInfoCount = 1,
819  .pWaitSemaphoreInfos = e->sem_wait,
820  .waitSemaphoreInfoCount = e->sem_wait_cnt,
821  .pSignalSemaphoreInfos = e->sem_sig,
822  .signalSemaphoreInfoCount = e->sem_sig_cnt,
823  };
824 
825  ret = vk->EndCommandBuffer(e->buf);
826  if (ret != VK_SUCCESS) {
827  av_log(s, AV_LOG_ERROR, "Unable to finish command buffer: %s\n",
828  ff_vk_ret2str(ret));
830  return AVERROR_EXTERNAL;
831  }
832 
833  s->hwctx->lock_queue(s->device, e->qf, e->qi);
834  ret = vk->QueueSubmit2(e->queue, 1, &submit_info, e->fence);
835  s->hwctx->unlock_queue(s->device, e->qf, e->qi);
836 
837  if (ret != VK_SUCCESS) {
838  av_log(s, AV_LOG_ERROR, "Unable to submit command buffer: %s\n",
839  ff_vk_ret2str(ret));
841  return AVERROR_EXTERNAL;
842  }
843 
844  for (int i = 0; i < e->sem_sig_val_dst_cnt; i++)
845  *e->sem_sig_val_dst[i] += 1;
846 
847  /* Unlock all frames */
848  for (int j = 0; j < e->nb_frame_deps; j++) {
849  if (e->frame_locked[j]) {
850  AVFrame *f = e->frame_deps[j];
851  AVHWFramesContext *hwfc = (AVHWFramesContext *)f->hw_frames_ctx->data;
852  AVVulkanFramesContext *vkfc = hwfc->hwctx;
853  AVVkFrame *vkf = (AVVkFrame *)f->data[0];
854 
855  if (e->frame_update[j]) {
856  int nb_images = ff_vk_count_images(vkf);
857  for (int i = 0; i < nb_images; i++) {
858  vkf->layout[i] = e->layout_dst[j];
859  vkf->access[i] = e->access_dst[j];
860  vkf->queue_family[i] = e->queue_family_dst[j];
861  }
862  }
863  vkfc->unlock_frame(hwfc, vkf);
864  e->frame_locked[j] = 0;
865  }
866  }
867 
868  e->had_submission = 1;
869 
870  return 0;
871 }
872 
873 int ff_vk_alloc_mem(FFVulkanContext *s, VkMemoryRequirements *req,
874  VkMemoryPropertyFlagBits req_flags, void *alloc_extension,
875  VkMemoryPropertyFlagBits *mem_flags, VkDeviceMemory *mem)
876 {
877  VkResult ret;
878  int index = -1;
879  FFVulkanFunctions *vk = &s->vkfn;
880 
881  VkMemoryAllocateInfo alloc_info = {
882  .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
883  .pNext = alloc_extension,
884  };
885 
886  /* Align if we need to */
887  if ((req_flags != UINT32_MAX) && req_flags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT)
888  req->size = FFALIGN(req->size, s->props.properties.limits.minMemoryMapAlignment);
889 
890  alloc_info.allocationSize = req->size;
891 
892  /* The vulkan spec requires memory types to be sorted in the "optimal"
893  * order, so the first matching type we find will be the best/fastest one */
894  for (int i = 0; i < s->mprops.memoryTypeCount; i++) {
895  /* The memory type must be supported by the requirements (bitfield) */
896  if (!(req->memoryTypeBits & (1 << i)))
897  continue;
898 
899  /* The memory type flags must include our properties */
900  if ((req_flags != UINT32_MAX) &&
901  ((s->mprops.memoryTypes[i].propertyFlags & req_flags) != req_flags))
902  continue;
903 
904  /* Found a suitable memory type */
905  index = i;
906  break;
907  }
908 
909  if (index < 0) {
910  av_log(s, AV_LOG_ERROR, "No memory type found for flags 0x%x\n",
911  req_flags);
912  return AVERROR(EINVAL);
913  }
914 
915  alloc_info.memoryTypeIndex = index;
916 
917  ret = vk->AllocateMemory(s->hwctx->act_dev, &alloc_info,
918  s->hwctx->alloc, mem);
919  if (ret != VK_SUCCESS)
920  return AVERROR(ENOMEM);
921 
922  if (mem_flags)
923  *mem_flags |= s->mprops.memoryTypes[index].propertyFlags;
924 
925  return 0;
926 }
927 
929  void *pNext, void *alloc_pNext,
930  VkBufferUsageFlags usage, VkMemoryPropertyFlagBits flags)
931 {
932  int err;
933  VkResult ret;
934  int use_ded_mem;
935  FFVulkanFunctions *vk = &s->vkfn;
936 
937  VkBufferCreateInfo buf_spawn = {
938  .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
939  .pNext = pNext,
940  .usage = usage,
941  .sharingMode = VK_SHARING_MODE_EXCLUSIVE,
942  .size = size, /* Gets FFALIGNED during alloc if host visible
943  but should be ok */
944  };
945 
946  VkMemoryAllocateFlagsInfo alloc_flags = {
947  .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_FLAGS_INFO,
948  .flags = VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT,
949  };
950  VkBufferMemoryRequirementsInfo2 req_desc = {
951  .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_REQUIREMENTS_INFO_2,
952  };
953  VkMemoryDedicatedAllocateInfo ded_alloc = {
954  .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO,
955  .pNext = alloc_pNext,
956  };
957  VkMemoryDedicatedRequirements ded_req = {
958  .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS,
959  };
960  VkMemoryRequirements2 req = {
961  .sType = VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2,
962  .pNext = &ded_req,
963  };
964 
965  ret = vk->CreateBuffer(s->hwctx->act_dev, &buf_spawn, s->hwctx->alloc, &buf->buf);
966  if (ret != VK_SUCCESS) {
967  av_log(s, AV_LOG_ERROR, "Failed to create buffer: %s\n",
968  ff_vk_ret2str(ret));
969  return AVERROR_EXTERNAL;
970  }
971 
972  req_desc.buffer = buf->buf;
973 
974  vk->GetBufferMemoryRequirements2(s->hwctx->act_dev, &req_desc, &req);
975 
976  /* In case the implementation prefers/requires dedicated allocation */
977  use_ded_mem = ded_req.prefersDedicatedAllocation |
978  ded_req.requiresDedicatedAllocation;
979  if (use_ded_mem) {
980  ded_alloc.buffer = buf->buf;
981  ded_alloc.pNext = alloc_pNext;
982  alloc_pNext = &ded_alloc;
983  }
984 
985  if (usage & VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT) {
986  alloc_flags.pNext = alloc_pNext;
987  alloc_pNext = &alloc_flags;
988  }
989 
990  err = ff_vk_alloc_mem(s, &req.memoryRequirements, flags, alloc_pNext,
991  &buf->flags, &buf->mem);
992  if (err)
993  return err;
994 
995  ret = vk->BindBufferMemory(s->hwctx->act_dev, buf->buf, buf->mem, 0);
996  if (ret != VK_SUCCESS) {
997  av_log(s, AV_LOG_ERROR, "Failed to bind memory to buffer: %s\n",
998  ff_vk_ret2str(ret));
999  return AVERROR_EXTERNAL;
1000  }
1001 
1002  if (usage & VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT) {
1003  VkBufferDeviceAddressInfo address_info = {
1004  .sType = VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO,
1005  .buffer = buf->buf,
1006  };
1007  buf->address = vk->GetBufferDeviceAddress(s->hwctx->act_dev, &address_info);
1008  }
1009 
1010  buf->size = size;
1011 
1012  return 0;
1013 }
1014 
1015 static void destroy_avvkbuf(void *opaque, uint8_t *data)
1016 {
1017  FFVulkanContext *s = opaque;
1018  FFVkBuffer *buf = (FFVkBuffer *)data;
1019  ff_vk_free_buf(s, buf);
1020  av_free(buf);
1021 }
1022 
1024  void *pNext, void *alloc_pNext,
1025  VkBufferUsageFlags usage, VkMemoryPropertyFlagBits flags)
1026 {
1027  int err;
1028  AVBufferRef *buf;
1029  FFVkBuffer *vkb = av_mallocz(sizeof(*vkb));
1030  if (!vkb)
1031  return AVERROR(ENOMEM);
1032 
1033  err = ff_vk_create_buf(s, vkb, size, pNext, alloc_pNext, usage, flags);
1034  if (err < 0) {
1035  av_free(vkb);
1036  return err;
1037  }
1038 
1039  buf = av_buffer_create((uint8_t *)vkb, sizeof(*vkb), destroy_avvkbuf, s, 0);
1040  if (!buf) {
1041  destroy_avvkbuf(s, (uint8_t *)vkb);
1042  return AVERROR(ENOMEM);
1043  }
1044 
1045  *ref = buf;
1046 
1047  return 0;
1048 }
1049 
1050 int ff_vk_map_buffers(FFVulkanContext *s, FFVkBuffer **buf, uint8_t *mem[],
1051  int nb_buffers, int invalidate)
1052 {
1053  VkResult ret;
1054  FFVulkanFunctions *vk = &s->vkfn;
1055  VkMappedMemoryRange inval_list[64];
1056  int inval_count = 0;
1057 
1058  for (int i = 0; i < nb_buffers; i++) {
1059  void *dst;
1060  ret = vk->MapMemory(s->hwctx->act_dev, buf[i]->mem, 0,
1061  VK_WHOLE_SIZE, 0, &dst);
1062  if (ret != VK_SUCCESS) {
1063  av_log(s, AV_LOG_ERROR, "Failed to map buffer memory: %s\n",
1064  ff_vk_ret2str(ret));
1065  return AVERROR_EXTERNAL;
1066  }
1067  mem[i] = dst;
1068  }
1069 
1070  if (!invalidate)
1071  return 0;
1072 
1073  for (int i = 0; i < nb_buffers; i++) {
1074  const VkMappedMemoryRange ival_buf = {
1075  .sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,
1076  .memory = buf[i]->mem,
1077  .size = VK_WHOLE_SIZE,
1078  };
1079  if (buf[i]->flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)
1080  continue;
1081  inval_list[inval_count++] = ival_buf;
1082  }
1083 
1084  if (inval_count) {
1085  ret = vk->InvalidateMappedMemoryRanges(s->hwctx->act_dev, inval_count,
1086  inval_list);
1087  if (ret != VK_SUCCESS) {
1088  av_log(s, AV_LOG_ERROR, "Failed to invalidate memory: %s\n",
1089  ff_vk_ret2str(ret));
1090  return AVERROR_EXTERNAL;
1091  }
1092  }
1093 
1094  return 0;
1095 }
1096 
1097 int ff_vk_unmap_buffers(FFVulkanContext *s, FFVkBuffer **buf, int nb_buffers,
1098  int flush)
1099 {
1100  int err = 0;
1101  VkResult ret;
1102  FFVulkanFunctions *vk = &s->vkfn;
1103  VkMappedMemoryRange flush_list[64];
1104  int flush_count = 0;
1105 
1106  if (flush) {
1107  for (int i = 0; i < nb_buffers; i++) {
1108  const VkMappedMemoryRange flush_buf = {
1109  .sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,
1110  .memory = buf[i]->mem,
1111  .size = VK_WHOLE_SIZE,
1112  };
1113  if (buf[i]->flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)
1114  continue;
1115  flush_list[flush_count++] = flush_buf;
1116  }
1117  }
1118 
1119  if (flush_count) {
1120  ret = vk->FlushMappedMemoryRanges(s->hwctx->act_dev, flush_count,
1121  flush_list);
1122  if (ret != VK_SUCCESS) {
1123  av_log(s, AV_LOG_ERROR, "Failed to flush memory: %s\n",
1124  ff_vk_ret2str(ret));
1125  err = AVERROR_EXTERNAL; /* We still want to try to unmap them */
1126  }
1127  }
1128 
1129  for (int i = 0; i < nb_buffers; i++)
1130  vk->UnmapMemory(s->hwctx->act_dev, buf[i]->mem);
1131 
1132  return err;
1133 }
1134 
1136 {
1137  FFVulkanFunctions *vk = &s->vkfn;
1138 
1139  if (!buf || !s->hwctx)
1140  return;
1141 
1142  if (buf->mapped_mem)
1143  ff_vk_unmap_buffer(s, buf, 0);
1144  if (buf->buf != VK_NULL_HANDLE)
1145  vk->DestroyBuffer(s->hwctx->act_dev, buf->buf, s->hwctx->alloc);
1146  if (buf->mem != VK_NULL_HANDLE)
1147  vk->FreeMemory(s->hwctx->act_dev, buf->mem, s->hwctx->alloc);
1148 }
1149 
1150 static void free_data_buf(void *opaque, uint8_t *data)
1151 {
1152  FFVulkanContext *ctx = opaque;
1153  FFVkBuffer *buf = (FFVkBuffer *)data;
1154  ff_vk_free_buf(ctx, buf);
1155  av_free(data);
1156 }
1157 
1158 static AVBufferRef *alloc_data_buf(void *opaque, size_t size)
1159 {
1160  AVBufferRef *ref;
1161  uint8_t *buf = av_mallocz(size);
1162  if (!buf)
1163  return NULL;
1164 
1165  ref = av_buffer_create(buf, size, free_data_buf, opaque, 0);
1166  if (!ref)
1167  av_free(buf);
1168  return ref;
1169 }
1170 
1172  AVBufferRef **buf, VkBufferUsageFlags usage,
1173  void *create_pNext, size_t size,
1174  VkMemoryPropertyFlagBits mem_props)
1175 {
1176  int err;
1177  AVBufferRef *ref;
1178  FFVkBuffer *data;
1179 
1180  if (!(*buf_pool)) {
1181  *buf_pool = av_buffer_pool_init2(sizeof(FFVkBuffer), ctx,
1182  alloc_data_buf, NULL);
1183  if (!(*buf_pool))
1184  return AVERROR(ENOMEM);
1185  }
1186 
1187  *buf = ref = av_buffer_pool_get(*buf_pool);
1188  if (!ref)
1189  return AVERROR(ENOMEM);
1190 
1191  data = (FFVkBuffer *)ref->data;
1192  data->stage = VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT;
1193  data->access = VK_ACCESS_2_NONE;
1194 
1195  if (data->size >= size)
1196  return 0;
1197 
1199  memset(data, 0, sizeof(*data));
1200 
1201  av_log(ctx, AV_LOG_DEBUG, "Allocating buffer of %"SIZE_SPECIFIER" bytes for pool %p\n",
1202  size, *buf_pool);
1203 
1204  err = ff_vk_create_buf(ctx, data, size,
1205  create_pNext, NULL, usage,
1206  mem_props);
1207  if (err < 0) {
1208  av_buffer_unref(&ref);
1209  return err;
1210  }
1211 
1212  if (mem_props & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) {
1213  err = ff_vk_map_buffer(ctx, data, &data->mapped_mem, 0);
1214  if (err < 0) {
1215  av_buffer_unref(&ref);
1216  return err;
1217  }
1218  }
1219 
1220  return 0;
1221 }
1222 
1224  VkShaderStageFlagBits stage)
1225 {
1226  VkPushConstantRange *pc;
1227 
1229  sizeof(*shd->push_consts),
1230  shd->push_consts_num + 1);
1231  if (!shd->push_consts)
1232  return AVERROR(ENOMEM);
1233 
1234  pc = &shd->push_consts[shd->push_consts_num++];
1235  memset(pc, 0, sizeof(*pc));
1236 
1237  pc->stageFlags = stage;
1238  pc->offset = offset;
1239  pc->size = size;
1240 
1241  return 0;
1242 }
1243 
1244 int ff_vk_init_sampler(FFVulkanContext *s, VkSampler *sampler,
1245  int unnorm_coords, VkFilter filt)
1246 {
1247  VkResult ret;
1248  FFVulkanFunctions *vk = &s->vkfn;
1249 
1250  VkSamplerCreateInfo sampler_info = {
1251  .sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,
1252  .magFilter = filt,
1253  .minFilter = sampler_info.magFilter,
1254  .mipmapMode = unnorm_coords ? VK_SAMPLER_MIPMAP_MODE_NEAREST :
1255  VK_SAMPLER_MIPMAP_MODE_LINEAR,
1256  .addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
1257  .addressModeV = sampler_info.addressModeU,
1258  .addressModeW = sampler_info.addressModeU,
1259  .anisotropyEnable = VK_FALSE,
1260  .compareOp = VK_COMPARE_OP_NEVER,
1261  .borderColor = VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK,
1262  .unnormalizedCoordinates = unnorm_coords,
1263  };
1264 
1265  ret = vk->CreateSampler(s->hwctx->act_dev, &sampler_info,
1266  s->hwctx->alloc, sampler);
1267  if (ret != VK_SUCCESS) {
1268  av_log(s, AV_LOG_ERROR, "Unable to init sampler: %s\n",
1269  ff_vk_ret2str(ret));
1270  return AVERROR_EXTERNAL;
1271  }
1272 
1273  return 0;
1274 }
1275 
1277 {
1285  return 1;
1286  return 0;
1287 }
1288 
1290 {
1292  const int high = desc->comp[0].depth > 8;
1293  return high ? "rgba16f" : "rgba8";
1294 }
1295 
1296 typedef struct ImageViewCtx {
1298  VkImageView views[];
1299 } ImageViewCtx;
1300 
1301 static void destroy_imageviews(void *opaque, uint8_t *data)
1302 {
1303  FFVulkanContext *s = opaque;
1304  FFVulkanFunctions *vk = &s->vkfn;
1305  ImageViewCtx *iv = (ImageViewCtx *)data;
1306 
1307  for (int i = 0; i < iv->nb_views; i++)
1308  vk->DestroyImageView(s->hwctx->act_dev, iv->views[i], s->hwctx->alloc);
1309 
1310  av_free(iv);
1311 }
1312 
1314  VkImageView views[AV_NUM_DATA_POINTERS],
1315  AVFrame *f)
1316 {
1317  int err;
1318  VkResult ret;
1319  AVBufferRef *buf;
1320  FFVulkanFunctions *vk = &s->vkfn;
1321  AVHWFramesContext *hwfc = (AVHWFramesContext *)f->hw_frames_ctx->data;
1322  const VkFormat *rep_fmts = av_vkfmt_from_pixfmt(hwfc->sw_format);
1323  AVVkFrame *vkf = (AVVkFrame *)f->data[0];
1324  const int nb_images = ff_vk_count_images(vkf);
1325  const int nb_planes = av_pix_fmt_count_planes(hwfc->sw_format);
1326 
1327  const size_t buf_size = sizeof(int) + nb_planes*sizeof(VkImageView);
1328  ImageViewCtx *iv = av_mallocz(buf_size);
1329  if (!iv)
1330  return AVERROR(ENOMEM);
1331 
1332  for (int i = 0; i < nb_planes; i++) {
1333  VkImageAspectFlags plane_aspect[] = { VK_IMAGE_ASPECT_COLOR_BIT,
1334  VK_IMAGE_ASPECT_PLANE_0_BIT,
1335  VK_IMAGE_ASPECT_PLANE_1_BIT,
1336  VK_IMAGE_ASPECT_PLANE_2_BIT, };
1337 
1338  VkImageViewCreateInfo view_create_info = {
1339  .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
1340  .pNext = NULL,
1341  .image = vkf->img[FFMIN(i, nb_images - 1)],
1342  .viewType = VK_IMAGE_VIEW_TYPE_2D,
1343  .format = rep_fmts[i],
1344  .components = ff_comp_identity_map,
1345  .subresourceRange = {
1346  .aspectMask = plane_aspect[(nb_planes != nb_images) +
1347  i*(nb_planes != nb_images)],
1348  .levelCount = 1,
1349  .layerCount = 1,
1350  },
1351  };
1352 
1353  ret = vk->CreateImageView(s->hwctx->act_dev, &view_create_info,
1354  s->hwctx->alloc, &iv->views[i]);
1355  if (ret != VK_SUCCESS) {
1356  av_log(s, AV_LOG_ERROR, "Failed to create imageview: %s\n",
1357  ff_vk_ret2str(ret));
1358  err = AVERROR_EXTERNAL;
1359  goto fail;
1360  }
1361 
1362  iv->nb_views++;
1363  }
1364 
1365  buf = av_buffer_create((uint8_t *)iv, buf_size, destroy_imageviews, s, 0);
1366  if (!buf) {
1367  err = AVERROR(ENOMEM);
1368  goto fail;
1369  }
1370 
1371  /* Add to queue dependencies */
1372  err = ff_vk_exec_add_dep_buf(s, e, &buf, 1, 0);
1373  if (err < 0)
1374  av_buffer_unref(&buf);
1375 
1376  memcpy(views, iv->views, nb_planes*sizeof(*views));
1377 
1378  return err;
1379 
1380 fail:
1381  for (int i = 0; i < iv->nb_views; i++)
1382  vk->DestroyImageView(s->hwctx->act_dev, iv->views[i], s->hwctx->alloc);
1383  av_free(iv);
1384  return err;
1385 }
1386 
1388  AVFrame *pic, VkImageMemoryBarrier2 *bar, int *nb_bar,
1389  VkPipelineStageFlags src_stage,
1390  VkPipelineStageFlags dst_stage,
1391  VkAccessFlagBits new_access,
1392  VkImageLayout new_layout,
1393  uint32_t new_qf)
1394 {
1395  int found = -1;
1396  AVVkFrame *vkf = (AVVkFrame *)pic->data[0];
1397  const int nb_images = ff_vk_count_images(vkf);
1398  for (int i = 0; i < e->nb_frame_deps; i++)
1399  if (e->frame_deps[i]->data[0] == pic->data[0]) {
1400  if (e->frame_update[i])
1401  found = i;
1402  break;
1403  }
1404 
1405  for (int i = 0; i < nb_images; i++) {
1406  bar[*nb_bar] = (VkImageMemoryBarrier2) {
1407  .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2,
1408  .pNext = NULL,
1409  .srcStageMask = src_stage,
1410  .dstStageMask = dst_stage,
1411  .srcAccessMask = found >= 0 ? e->access_dst[found] : vkf->access[i],
1412  .dstAccessMask = new_access,
1413  .oldLayout = found >= 0 ? e->layout_dst[found] : vkf->layout[0],
1414  .newLayout = new_layout,
1415  .srcQueueFamilyIndex = found >= 0 ? e->queue_family_dst[found] : vkf->queue_family[0],
1416  .dstQueueFamilyIndex = new_qf,
1417  .image = vkf->img[i],
1418  .subresourceRange = (VkImageSubresourceRange) {
1419  .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
1420  .layerCount = 1,
1421  .levelCount = 1,
1422  },
1423  };
1424  *nb_bar += 1;
1425  }
1426 
1427  ff_vk_exec_update_frame(s, e, pic, &bar[*nb_bar - nb_images], NULL);
1428 }
1429 
1431  VkPipelineStageFlags stage,
1432  const char *extensions[], int nb_extensions,
1433  int lg_x, int lg_y, int lg_z,
1434  uint32_t required_subgroup_size)
1435 {
1437 
1438  shd->name = name;
1439  shd->stage = stage;
1440  shd->lg_size[0] = lg_x;
1441  shd->lg_size[1] = lg_y;
1442  shd->lg_size[2] = lg_z;
1443 
1444  switch (shd->stage) {
1445  case VK_SHADER_STAGE_ANY_HIT_BIT_KHR:
1446  case VK_SHADER_STAGE_CALLABLE_BIT_KHR:
1447  case VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR:
1448  case VK_SHADER_STAGE_INTERSECTION_BIT_KHR:
1449  case VK_SHADER_STAGE_MISS_BIT_KHR:
1450  case VK_SHADER_STAGE_RAYGEN_BIT_KHR:
1451  shd->bind_point = VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR;
1452  break;
1453  case VK_SHADER_STAGE_COMPUTE_BIT:
1454  shd->bind_point = VK_PIPELINE_BIND_POINT_COMPUTE;
1455  break;
1456  default:
1457  shd->bind_point = VK_PIPELINE_BIND_POINT_GRAPHICS;
1458  break;
1459  };
1460 
1461  if (required_subgroup_size) {
1462  shd->subgroup_info.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_REQUIRED_SUBGROUP_SIZE_CREATE_INFO;
1463  shd->subgroup_info.requiredSubgroupSize = required_subgroup_size;
1464  }
1465 
1466  av_bprintf(&shd->src, "/* %s shader: %s */\n",
1467  (stage == VK_SHADER_STAGE_TASK_BIT_EXT ||
1468  stage == VK_SHADER_STAGE_MESH_BIT_EXT) ?
1469  "Mesh" :
1470  (shd->bind_point == VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR) ?
1471  "Raytrace" :
1472  (shd->bind_point == VK_PIPELINE_BIND_POINT_COMPUTE) ?
1473  "Compute" : "Graphics",
1474  name);
1475  GLSLF(0, #version %i ,460);
1476  GLSLC(0, );
1477 
1478  /* Common utilities */
1479  GLSLC(0, #define IS_WITHIN(v1, v2) ((v1.x < v2.x) && (v1.y < v2.y)) );
1480  GLSLC(0, );
1481  GLSLC(0, #extension GL_EXT_scalar_block_layout : require );
1482  if ((s->extensions & FF_VK_EXT_DEBUG_UTILS) &&
1483  (s->extensions & FF_VK_EXT_RELAXED_EXTENDED_INSTR))
1484  GLSLC(0, #extension GL_EXT_debug_printf : require );
1485 
1486  if (stage == VK_SHADER_STAGE_TASK_BIT_EXT ||
1487  stage == VK_SHADER_STAGE_MESH_BIT_EXT)
1488  GLSLC(0, #extension GL_EXT_mesh_shader : require );
1489 
1490  for (int i = 0; i < nb_extensions; i++)
1491  GLSLF(0, #extension %s : %s ,extensions[i], "require");
1492  GLSLC(0, );
1493 
1494  GLSLF(0, layout (local_size_x = %i, local_size_y = %i, local_size_z = %i) in;
1495  , shd->lg_size[0], shd->lg_size[1], shd->lg_size[2]);
1496  GLSLC(0, );
1497 
1498  return 0;
1499 }
1500 
1501 void ff_vk_shader_print(void *ctx, FFVulkanShader *shd, int prio)
1502 {
1503  int line = 0;
1504  const char *p = shd->src.str;
1505  const char *start = p;
1506  const size_t len = strlen(p);
1507 
1508  AVBPrint buf;
1510 
1511  for (int i = 0; i < len; i++) {
1512  if (p[i] == '\n') {
1513  av_bprintf(&buf, "%i\t", ++line);
1514  av_bprint_append_data(&buf, start, &p[i] - start + 1);
1515  start = &p[i + 1];
1516  }
1517  }
1518 
1519  av_log(ctx, prio, "Shader %s: \n%s", shd->name, buf.str);
1520  av_bprint_finalize(&buf, NULL);
1521 }
1522 
1524 {
1525  VkResult ret;
1526  FFVulkanFunctions *vk = &s->vkfn;
1527  VkPipelineLayoutCreateInfo pipeline_layout_info;
1528 
1529  /* Finally create the pipeline layout */
1530  pipeline_layout_info = (VkPipelineLayoutCreateInfo) {
1531  .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
1532  .pSetLayouts = shd->desc_layout,
1533  .setLayoutCount = shd->nb_descriptor_sets,
1534  .pushConstantRangeCount = shd->push_consts_num,
1535  .pPushConstantRanges = shd->push_consts,
1536  };
1537 
1538  ret = vk->CreatePipelineLayout(s->hwctx->act_dev, &pipeline_layout_info,
1539  s->hwctx->alloc, &shd->pipeline_layout);
1540  if (ret != VK_SUCCESS) {
1541  av_log(s, AV_LOG_ERROR, "Unable to init pipeline layout: %s\n",
1542  ff_vk_ret2str(ret));
1543  return AVERROR_EXTERNAL;
1544  }
1545 
1546  return 0;
1547 }
1548 
1550  VkShaderModule *mod,
1551  uint8_t *spirv, size_t spirv_len)
1552 {
1553  VkResult ret;
1554  FFVulkanFunctions *vk = &s->vkfn;
1555 
1556  VkShaderModuleCreateInfo shader_module_info = {
1557  .sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO,
1558  .pNext = NULL,
1559  .flags = 0x0,
1560  .pCode = (void *)spirv,
1561  .codeSize = spirv_len,
1562  };
1563 
1564  ret = vk->CreateShaderModule(s->hwctx->act_dev, &shader_module_info,
1565  s->hwctx->alloc, mod);
1566  if (ret != VK_SUCCESS) {
1567  av_log(s, AV_LOG_VERBOSE, "Error creating shader module: %s\n",
1568  ff_vk_ret2str(ret));
1569  return AVERROR_EXTERNAL;
1570  }
1571 
1572  return 0;
1573 }
1574 
1576  VkShaderModule mod, const char *entrypoint)
1577 {
1578  VkResult ret;
1579  FFVulkanFunctions *vk = &s->vkfn;
1580 
1581  VkComputePipelineCreateInfo pipeline_create_info = {
1582  .sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,
1583  .flags = (s->extensions & FF_VK_EXT_DESCRIPTOR_BUFFER) ?
1584  VK_PIPELINE_CREATE_DESCRIPTOR_BUFFER_BIT_EXT : 0x0,
1585  .layout = shd->pipeline_layout,
1586  .stage = (VkPipelineShaderStageCreateInfo) {
1587  .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
1588  .pNext = shd->subgroup_info.requiredSubgroupSize ?
1589  &shd->subgroup_info : NULL,
1590  .pName = entrypoint,
1591  .flags = shd->subgroup_info.requiredSubgroupSize ?
1592  VK_PIPELINE_SHADER_STAGE_CREATE_REQUIRE_FULL_SUBGROUPS_BIT : 0x0,
1593  .stage = shd->stage,
1594  .module = mod,
1595  },
1596  };
1597 
1598  ret = vk->CreateComputePipelines(s->hwctx->act_dev, VK_NULL_HANDLE, 1,
1599  &pipeline_create_info,
1600  s->hwctx->alloc, &shd->pipeline);
1601  if (ret != VK_SUCCESS) {
1602  av_log(s, AV_LOG_ERROR, "Unable to init compute pipeline: %s\n",
1603  ff_vk_ret2str(ret));
1604  return AVERROR_EXTERNAL;
1605  }
1606 
1607  return 0;
1608 }
1609 
1611  uint8_t *spirv, size_t spirv_len,
1612  const char *entrypoint)
1613 {
1614  VkResult ret;
1615  FFVulkanFunctions *vk = &s->vkfn;
1616  size_t shader_size = 0;
1617 
1618  VkShaderCreateInfoEXT shader_obj_create = {
1619  .sType = VK_STRUCTURE_TYPE_SHADER_CREATE_INFO_EXT,
1620  .flags = shd->subgroup_info.requiredSubgroupSize ?
1621  VK_SHADER_CREATE_REQUIRE_FULL_SUBGROUPS_BIT_EXT : 0x0,
1622  .stage = shd->stage,
1623  .nextStage = 0,
1624  .codeType = VK_SHADER_CODE_TYPE_SPIRV_EXT,
1625  .pCode = spirv,
1626  .codeSize = spirv_len,
1627  .pName = entrypoint,
1628  .pSetLayouts = shd->desc_layout,
1629  .setLayoutCount = shd->nb_descriptor_sets,
1630  .pushConstantRangeCount = shd->push_consts_num,
1631  .pPushConstantRanges = shd->push_consts,
1632  .pSpecializationInfo = NULL,
1633  };
1634 
1635  ret = vk->CreateShadersEXT(s->hwctx->act_dev, 1, &shader_obj_create,
1636  s->hwctx->alloc, &shd->object);
1637  if (ret != VK_SUCCESS) {
1638  av_log(s, AV_LOG_ERROR, "Unable to create shader object: %s\n",
1639  ff_vk_ret2str(ret));
1640  return AVERROR_EXTERNAL;
1641  }
1642 
1643  if (vk->GetShaderBinaryDataEXT(s->hwctx->act_dev, shd->object,
1644  &shader_size, NULL) == VK_SUCCESS)
1645  av_log(s, AV_LOG_VERBOSE, "Shader %s size: %zu binary (%zu SPIR-V)\n",
1646  shd->name, shader_size, spirv_len);
1647 
1648  return 0;
1649 }
1650 
1652 {
1653  VkResult ret;
1654  FFVulkanFunctions *vk = &s->vkfn;
1655 
1657  sizeof(*shd->desc_layout));
1658  if (!shd->desc_layout)
1659  return AVERROR(ENOMEM);
1660 
1661  if (!(s->extensions & FF_VK_EXT_DESCRIPTOR_BUFFER)) {
1662  int has_singular = 0;
1663  for (int i = 0; i < shd->nb_descriptor_sets; i++) {
1664  if (shd->desc_set[i].singular) {
1665  has_singular = 1;
1666  break;
1667  }
1668  }
1669  shd->use_push = (s->extensions & FF_VK_EXT_PUSH_DESCRIPTOR) &&
1670  (shd->nb_descriptor_sets == 1) &&
1671  !has_singular;
1672  }
1673 
1674  for (int i = 0; i < shd->nb_descriptor_sets; i++) {
1675  FFVulkanDescriptorSet *set = &shd->desc_set[i];
1676  VkDescriptorSetLayoutCreateInfo desc_layout_create = {
1677  .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
1678  .bindingCount = set->nb_bindings,
1679  .pBindings = set->binding,
1680  .flags = (s->extensions & FF_VK_EXT_DESCRIPTOR_BUFFER) ?
1681  VK_DESCRIPTOR_SET_LAYOUT_CREATE_DESCRIPTOR_BUFFER_BIT_EXT :
1682  (shd->use_push) ?
1683  VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR :
1684  0x0,
1685  };
1686 
1687  ret = vk->CreateDescriptorSetLayout(s->hwctx->act_dev,
1688  &desc_layout_create,
1689  s->hwctx->alloc,
1690  &shd->desc_layout[i]);
1691  if (ret != VK_SUCCESS) {
1692  av_log(s, AV_LOG_ERROR, "Unable to create descriptor set layout: %s",
1693  ff_vk_ret2str(ret));
1694  return AVERROR_EXTERNAL;
1695  }
1696 
1697  if (s->extensions & FF_VK_EXT_DESCRIPTOR_BUFFER) {
1698  vk->GetDescriptorSetLayoutSizeEXT(s->hwctx->act_dev, shd->desc_layout[i],
1699  &set->layout_size);
1700 
1701  set->aligned_size = FFALIGN(set->layout_size,
1702  s->desc_buf_props.descriptorBufferOffsetAlignment);
1703 
1704  for (int j = 0; j < set->nb_bindings; j++)
1705  vk->GetDescriptorSetLayoutBindingOffsetEXT(s->hwctx->act_dev,
1706  shd->desc_layout[i],
1707  j,
1708  &set->binding_offset[j]);
1709  }
1710  }
1711 
1712  return 0;
1713 }
1714 
1716  uint8_t *spirv, size_t spirv_len,
1717  const char *entrypoint)
1718 {
1719  int err;
1720  FFVulkanFunctions *vk = &s->vkfn;
1721 
1722  err = init_descriptors(s, shd);
1723  if (err < 0)
1724  return err;
1725 
1726  err = init_pipeline_layout(s, shd);
1727  if (err < 0)
1728  return err;
1729 
1730  if (s->extensions & FF_VK_EXT_DESCRIPTOR_BUFFER) {
1732  sizeof(*shd->bound_buffer_indices));
1733  if (!shd->bound_buffer_indices)
1734  return AVERROR(ENOMEM);
1735 
1736  for (int i = 0; i < shd->nb_descriptor_sets; i++)
1737  shd->bound_buffer_indices[i] = i;
1738  }
1739 
1740  if (s->extensions & FF_VK_EXT_SHADER_OBJECT) {
1741  err = create_shader_object(s, shd, spirv, spirv_len, entrypoint);
1742  if (err < 0)
1743  return err;
1744  } else {
1745  VkShaderModule mod;
1746  err = create_shader_module(s, shd, &mod, spirv, spirv_len);
1747  if (err < 0)
1748  return err;
1749 
1750  switch (shd->bind_point) {
1751  case VK_PIPELINE_BIND_POINT_COMPUTE:
1752  err = init_compute_pipeline(s, shd, mod, entrypoint);
1753  break;
1754  default:
1755  av_log(s, AV_LOG_ERROR, "Unsupported shader type: %i\n",
1756  shd->bind_point);
1757  err = AVERROR(EINVAL);
1758  break;
1759  };
1760 
1761  vk->DestroyShaderModule(s->hwctx->act_dev, mod, s->hwctx->alloc);
1762  if (err < 0)
1763  return err;
1764  }
1765 
1766  return 0;
1767 }
1768 
1769 static const struct descriptor_props {
1770  size_t struct_size; /* Size of the opaque which updates the descriptor */
1771  const char *type;
1773  int mem_quali; /* Can use a memory qualifier */
1774  int dim_needed; /* Must indicate dimension */
1775  int buf_content; /* Must indicate buffer contents */
1776 } descriptor_props[] = {
1777  [VK_DESCRIPTOR_TYPE_SAMPLER] = { sizeof(VkDescriptorImageInfo), "sampler", 1, 0, 0, 0, },
1778  [VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE] = { sizeof(VkDescriptorImageInfo), "texture", 1, 0, 1, 0, },
1779  [VK_DESCRIPTOR_TYPE_STORAGE_IMAGE] = { sizeof(VkDescriptorImageInfo), "image", 1, 1, 1, 0, },
1780  [VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT] = { sizeof(VkDescriptorImageInfo), "subpassInput", 1, 0, 0, 0, },
1781  [VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER] = { sizeof(VkDescriptorImageInfo), "sampler", 1, 0, 1, 0, },
1782  [VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER] = { sizeof(VkDescriptorBufferInfo), NULL, 1, 0, 0, 1, },
1783  [VK_DESCRIPTOR_TYPE_STORAGE_BUFFER] = { sizeof(VkDescriptorBufferInfo), "buffer", 0, 1, 0, 1, },
1784  [VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC] = { sizeof(VkDescriptorBufferInfo), NULL, 1, 0, 0, 1, },
1785  [VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC] = { sizeof(VkDescriptorBufferInfo), "buffer", 0, 1, 0, 1, },
1786  [VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER] = { sizeof(VkBufferView), "samplerBuffer", 1, 0, 0, 0, },
1787  [VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER] = { sizeof(VkBufferView), "imageBuffer", 1, 0, 0, 0, },
1788 };
1789 
1792  int singular, int print_to_shader_only)
1793 {
1794  int has_sampler = 0;
1796 
1797  if (print_to_shader_only)
1798  goto print;
1799 
1800  /* Actual layout allocated for the pipeline */
1801  set = av_realloc_array(shd->desc_set,
1802  sizeof(*shd->desc_set),
1803  shd->nb_descriptor_sets + 1);
1804  if (!set)
1805  return AVERROR(ENOMEM);
1806  shd->desc_set = set;
1807 
1808  set = &set[shd->nb_descriptor_sets];
1809  memset(set, 0, sizeof(*set));
1810 
1811  set->binding = av_calloc(nb, sizeof(*set->binding));
1812  if (!set->binding)
1813  return AVERROR(ENOMEM);
1814 
1815  set->binding_offset = av_calloc(nb, sizeof(*set->binding_offset));
1816  if (!set->binding_offset) {
1817  av_freep(&set->binding);
1818  return AVERROR(ENOMEM);
1819  }
1820 
1821  for (int i = 0; i < nb; i++) {
1822  set->binding[i].binding = i;
1823  set->binding[i].descriptorType = desc[i].type;
1824  set->binding[i].descriptorCount = FFMAX(desc[i].elems, 1);
1825  set->binding[i].stageFlags = desc[i].stages;
1826  set->binding[i].pImmutableSamplers = desc[i].samplers;
1827 
1828  if (desc[i].type == VK_DESCRIPTOR_TYPE_SAMPLER ||
1829  desc[i].type == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
1830  has_sampler |= 1;
1831  }
1832 
1833  set->usage = VK_BUFFER_USAGE_RESOURCE_DESCRIPTOR_BUFFER_BIT_EXT |
1834  VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT;
1835  if (has_sampler)
1836  set->usage |= VK_BUFFER_USAGE_SAMPLER_DESCRIPTOR_BUFFER_BIT_EXT;
1837 
1838  if (!(s->extensions & FF_VK_EXT_DESCRIPTOR_BUFFER)) {
1839  for (int i = 0; i < nb; i++) {
1840  int j;
1841  VkDescriptorPoolSize *desc_pool_size;
1842  for (j = 0; j < shd->nb_desc_pool_size; j++)
1843  if (shd->desc_pool_size[j].type == desc[i].type)
1844  break;
1845  if (j >= shd->nb_desc_pool_size) {
1846  desc_pool_size = av_realloc_array(shd->desc_pool_size,
1847  sizeof(*desc_pool_size),
1848  shd->nb_desc_pool_size + 1);
1849  if (!desc_pool_size)
1850  return AVERROR(ENOMEM);
1851 
1852  shd->desc_pool_size = desc_pool_size;
1853  shd->nb_desc_pool_size++;
1854  memset(&desc_pool_size[j], 0, sizeof(VkDescriptorPoolSize));
1855  }
1856  shd->desc_pool_size[j].type = desc[i].type;
1857  shd->desc_pool_size[j].descriptorCount += FFMAX(desc[i].elems, 1);
1858  }
1859  }
1860 
1861  set->singular = singular;
1862  set->nb_bindings = nb;
1863  shd->nb_descriptor_sets++;
1864 
1865 print:
1866  /* Write shader info */
1867  for (int i = 0; i < nb; i++) {
1868  const struct descriptor_props *prop = &descriptor_props[desc[i].type];
1869  GLSLA("layout (set = %i, binding = %i", shd->nb_descriptor_sets - 1, i);
1870 
1871  if (desc[i].mem_layout)
1872  GLSLA(", %s", desc[i].mem_layout);
1873  GLSLA(")");
1874 
1875  if (prop->is_uniform)
1876  GLSLA(" uniform");
1877 
1878  if (prop->mem_quali && desc[i].mem_quali)
1879  GLSLA(" %s", desc[i].mem_quali);
1880 
1881  if (prop->type)
1882  GLSLA(" %s", prop->type);
1883 
1884  if (prop->dim_needed)
1885  GLSLA("%iD", desc[i].dimensions);
1886 
1887  GLSLA(" %s", desc[i].name);
1888 
1889  if (prop->buf_content)
1890  GLSLA(" {\n %s\n}", desc[i].buf_content);
1891  else if (desc[i].elems > 0)
1892  GLSLA("[%i]", desc[i].elems);
1893 
1894  GLSLA(";");
1895  GLSLA("\n");
1896  }
1897  GLSLA("\n");
1898 
1899  return 0;
1900 }
1901 
1903  FFVulkanShader *shd)
1904 {
1905  int err;
1906  FFVulkanShaderData *sd;
1907 
1908  if (!shd->nb_descriptor_sets)
1909  return 0;
1910 
1911  sd = av_realloc_array(pool->reg_shd,
1912  sizeof(*pool->reg_shd),
1913  pool->nb_reg_shd + 1);
1914  if (!sd)
1915  return AVERROR(ENOMEM);
1916 
1917  pool->reg_shd = sd;
1918  sd = &sd[pool->nb_reg_shd++];
1919  memset(sd, 0, sizeof(*sd));
1920 
1921  sd->shd = shd;
1923 
1924  if (s->extensions & FF_VK_EXT_DESCRIPTOR_BUFFER) {
1925  sd->desc_bind = av_malloc_array(sd->nb_descriptor_sets, sizeof(*sd->desc_bind));
1926  if (!sd->desc_bind)
1927  return AVERROR(ENOMEM);
1928 
1929  sd->desc_set_buf = av_calloc(sd->nb_descriptor_sets, sizeof(*sd->desc_set_buf));
1930  if (!sd->desc_set_buf)
1931  return AVERROR(ENOMEM);
1932 
1933  for (int i = 0; i < sd->nb_descriptor_sets; i++) {
1934  FFVulkanDescriptorSet *set = &shd->desc_set[i];
1936  int nb = set->singular ? 1 : pool->pool_size;
1937 
1938  err = ff_vk_create_buf(s, &sdb->buf,
1939  set->aligned_size*nb,
1940  NULL, NULL, set->usage,
1941  VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT |
1942  VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
1943  VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
1944  if (err < 0)
1945  return err;
1946 
1947  err = ff_vk_map_buffer(s, &sdb->buf, &sdb->desc_mem, 0);
1948  if (err < 0)
1949  return err;
1950 
1951  sd->desc_bind[i] = (VkDescriptorBufferBindingInfoEXT) {
1952  .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_BUFFER_BINDING_INFO_EXT,
1953  .usage = set->usage,
1954  .address = sdb->buf.address,
1955  };
1956  }
1957  } else if (!shd->use_push) {
1958  VkResult ret;
1959  FFVulkanFunctions *vk = &s->vkfn;
1960  VkDescriptorSetLayout *tmp_layouts;
1961  VkDescriptorSetAllocateInfo set_alloc_info;
1962  VkDescriptorPoolCreateInfo pool_create_info;
1963 
1964  for (int i = 0; i < shd->nb_desc_pool_size; i++)
1965  shd->desc_pool_size[i].descriptorCount *= pool->pool_size;
1966 
1967  pool_create_info = (VkDescriptorPoolCreateInfo) {
1968  .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
1969  .flags = 0,
1970  .pPoolSizes = shd->desc_pool_size,
1971  .poolSizeCount = shd->nb_desc_pool_size,
1972  .maxSets = sd->nb_descriptor_sets*pool->pool_size,
1973  };
1974 
1975  ret = vk->CreateDescriptorPool(s->hwctx->act_dev, &pool_create_info,
1976  s->hwctx->alloc, &sd->desc_pool);
1977  if (ret != VK_SUCCESS) {
1978  av_log(s, AV_LOG_ERROR, "Unable to create descriptor pool: %s\n",
1979  ff_vk_ret2str(ret));
1980  return AVERROR_EXTERNAL;
1981  }
1982 
1983  tmp_layouts = av_malloc_array(pool_create_info.maxSets, sizeof(*tmp_layouts));
1984  if (!tmp_layouts)
1985  return AVERROR(ENOMEM);
1986 
1987  /* Colate each execution context's descriptor set layouts */
1988  for (int i = 0; i < pool->pool_size; i++)
1989  for (int j = 0; j < sd->nb_descriptor_sets; j++)
1990  tmp_layouts[i*sd->nb_descriptor_sets + j] = shd->desc_layout[j];
1991 
1992  set_alloc_info = (VkDescriptorSetAllocateInfo) {
1993  .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
1994  .descriptorPool = sd->desc_pool,
1995  .pSetLayouts = tmp_layouts,
1996  .descriptorSetCount = pool_create_info.maxSets,
1997  };
1998 
1999  sd->desc_sets = av_malloc_array(pool_create_info.maxSets,
2000  sizeof(*tmp_layouts));
2001  if (!sd->desc_sets) {
2002  av_free(tmp_layouts);
2003  return AVERROR(ENOMEM);
2004  }
2005  ret = vk->AllocateDescriptorSets(s->hwctx->act_dev, &set_alloc_info,
2006  sd->desc_sets);
2007  av_free(tmp_layouts);
2008  if (ret != VK_SUCCESS) {
2009  av_log(s, AV_LOG_ERROR, "Unable to allocate descriptor set: %s\n",
2010  ff_vk_ret2str(ret));
2011  av_freep(&sd->desc_sets);
2012  return AVERROR_EXTERNAL;
2013  }
2014  }
2015 
2016  return 0;
2017 }
2018 
2020  FFVulkanShader *shd)
2021 {
2022  for (int i = 0; i < e->parent->nb_reg_shd; i++)
2023  if (e->parent->reg_shd[i].shd == shd)
2024  return &e->parent->reg_shd[i];
2025  av_assert0(0);
2026 }
2027 
2029  FFVulkanShader *shd, int set,
2030  int bind_idx, int array_idx,
2031  VkDescriptorGetInfoEXT *desc_get_info,
2032  size_t desc_size)
2033 {
2034  FFVulkanFunctions *vk = &s->vkfn;
2035  FFVulkanDescriptorSet *desc_set = &shd->desc_set[set];
2036  FFVulkanShaderData *sd = get_shd_data(e, shd);
2037  const size_t exec_offset = desc_set->singular ? 0 : desc_set->aligned_size*e->idx;
2038 
2039  void *desc = sd->desc_set_buf[set].desc_mem + /* Base */
2040  exec_offset + /* Execution context */
2041  desc_set->binding_offset[bind_idx] + /* Descriptor binding */
2042  array_idx*desc_size; /* Array position */
2043 
2044  vk->GetDescriptorEXT(s->hwctx->act_dev, desc_get_info, desc_size, desc);
2045 }
2046 
2048  FFVulkanShader *shd, int set,
2049  VkWriteDescriptorSet *write_info)
2050 {
2051  FFVulkanFunctions *vk = &s->vkfn;
2052  FFVulkanDescriptorSet *desc_set = &shd->desc_set[set];
2053  FFVulkanShaderData *sd = get_shd_data(e, shd);
2054 
2055  if (desc_set->singular) {
2056  for (int i = 0; i < e->parent->pool_size; i++) {
2057  write_info->dstSet = sd->desc_sets[i*sd->nb_descriptor_sets + set];
2058  vk->UpdateDescriptorSets(s->hwctx->act_dev, 1, write_info, 0, NULL);
2059  }
2060  } else {
2061  if (shd->use_push) {
2062  vk->CmdPushDescriptorSetKHR(e->buf,
2063  shd->bind_point,
2064  shd->pipeline_layout,
2065  set, 1,
2066  write_info);
2067  } else {
2068  write_info->dstSet = sd->desc_sets[e->idx*sd->nb_descriptor_sets + set];
2069  vk->UpdateDescriptorSets(s->hwctx->act_dev, 1, write_info, 0, NULL);
2070  }
2071  }
2072 }
2073 
2075  FFVkExecContext *e, int set, int bind, int offs,
2076  VkImageView view, VkImageLayout layout,
2077  VkSampler sampler)
2078 {
2079  FFVulkanDescriptorSet *desc_set = &shd->desc_set[set];
2080 
2081  if (s->extensions & FF_VK_EXT_DESCRIPTOR_BUFFER) {
2082  VkDescriptorGetInfoEXT desc_get_info = {
2083  .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_GET_INFO_EXT,
2084  .type = desc_set->binding[bind].descriptorType,
2085  };
2086  VkDescriptorImageInfo desc_img_info = {
2087  .imageView = view,
2088  .sampler = sampler,
2089  .imageLayout = layout,
2090  };
2091  size_t desc_size;
2092 
2093  switch (desc_get_info.type) {
2094  case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
2095  desc_get_info.data.pSampledImage = &desc_img_info;
2096  desc_size = s->desc_buf_props.sampledImageDescriptorSize;
2097  break;
2098  case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
2099  desc_get_info.data.pStorageImage = &desc_img_info;
2100  desc_size = s->desc_buf_props.storageImageDescriptorSize;
2101  break;
2102  case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
2103  desc_get_info.data.pInputAttachmentImage = &desc_img_info;
2104  desc_size = s->desc_buf_props.inputAttachmentDescriptorSize;
2105  break;
2106  case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
2107  desc_get_info.data.pCombinedImageSampler = &desc_img_info;
2108  desc_size = s->desc_buf_props.combinedImageSamplerDescriptorSize;
2109  break;
2110  default:
2111  av_log(s, AV_LOG_ERROR, "Invalid descriptor type at set %i binding %i: %i!\n",
2112  set, bind, desc_get_info.type);
2113  return AVERROR(EINVAL);
2114  break;
2115  };
2116 
2117  update_set_descriptor(s, e, shd, set, bind, offs,
2118  &desc_get_info, desc_size);
2119  } else {
2120  VkDescriptorImageInfo desc_pool_write_info_img = {
2121  .sampler = sampler,
2122  .imageView = view,
2123  .imageLayout = layout,
2124  };
2125  VkWriteDescriptorSet desc_pool_write_info = {
2126  .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
2127  .dstBinding = bind,
2128  .descriptorCount = 1,
2129  .dstArrayElement = offs,
2130  .descriptorType = desc_set->binding[bind].descriptorType,
2131  .pImageInfo = &desc_pool_write_info_img,
2132  };
2133  update_set_pool_write(s, e, shd, set, &desc_pool_write_info);
2134  }
2135 
2136  return 0;
2137 }
2138 
2140  FFVulkanShader *shd,
2141  int set, int bind, int elem,
2142  FFVkBuffer *buf, VkDeviceSize offset, VkDeviceSize len,
2143  VkFormat fmt)
2144 {
2145  FFVulkanDescriptorSet *desc_set = &shd->desc_set[set];
2146 
2147  if (s->extensions & FF_VK_EXT_DESCRIPTOR_BUFFER) {
2148  VkDescriptorGetInfoEXT desc_get_info = {
2149  .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_GET_INFO_EXT,
2150  .type = desc_set->binding[bind].descriptorType,
2151  };
2152  VkDescriptorAddressInfoEXT desc_buf_info = {
2153  .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_ADDRESS_INFO_EXT,
2154  .address = buf->address + offset,
2155  .range = len,
2156  .format = fmt,
2157  };
2158  size_t desc_size;
2159 
2160  switch (desc_get_info.type) {
2161  case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
2162  desc_get_info.data.pUniformBuffer = &desc_buf_info;
2163  desc_size = s->desc_buf_props.uniformBufferDescriptorSize;
2164  break;
2165  case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
2166  desc_get_info.data.pStorageBuffer = &desc_buf_info;
2167  desc_size = s->desc_buf_props.storageBufferDescriptorSize;
2168  break;
2169  case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
2170  desc_get_info.data.pUniformTexelBuffer = &desc_buf_info;
2171  desc_size = s->desc_buf_props.uniformTexelBufferDescriptorSize;
2172  break;
2173  case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
2174  desc_get_info.data.pStorageTexelBuffer = &desc_buf_info;
2175  desc_size = s->desc_buf_props.storageTexelBufferDescriptorSize;
2176  break;
2177  default:
2178  av_log(s, AV_LOG_ERROR, "Invalid descriptor type at set %i binding %i: %i!\n",
2179  set, bind, desc_get_info.type);
2180  return AVERROR(EINVAL);
2181  break;
2182  };
2183 
2184  update_set_descriptor(s, e, shd, set, bind, elem, &desc_get_info, desc_size);
2185  } else {
2186  VkDescriptorBufferInfo desc_pool_write_info_buf = {
2187  .buffer = buf->buf,
2188  .offset = offset,
2189  .range = len,
2190  };
2191  VkWriteDescriptorSet desc_pool_write_info = {
2192  .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
2193  .dstBinding = bind,
2194  .descriptorCount = 1,
2195  .dstArrayElement = elem,
2196  .descriptorType = desc_set->binding[bind].descriptorType,
2197  .pBufferInfo = &desc_pool_write_info_buf,
2198  };
2199  update_set_pool_write(s, e, shd, set, &desc_pool_write_info);
2200  }
2201 
2202  return 0;
2203 }
2204 
2206  FFVulkanShader *shd, AVFrame *f,
2207  VkImageView *views, int set, int binding,
2208  VkImageLayout layout, VkSampler sampler)
2209 {
2210  AVHWFramesContext *hwfc = (AVHWFramesContext *)f->hw_frames_ctx->data;
2211  const int nb_planes = av_pix_fmt_count_planes(hwfc->sw_format);
2212 
2213  for (int i = 0; i < nb_planes; i++)
2214  vk_set_descriptor_image(s, shd, e, set, binding, i,
2215  views[i], layout, sampler);
2216 }
2217 
2219  FFVulkanShader *shd,
2220  VkShaderStageFlagBits stage,
2221  int offset, size_t size, void *src)
2222 {
2223  FFVulkanFunctions *vk = &s->vkfn;
2224  vk->CmdPushConstants(e->buf, shd->pipeline_layout,
2225  stage, offset, size, src);
2226 }
2227 
2229  FFVulkanShader *shd)
2230 {
2231  FFVulkanFunctions *vk = &s->vkfn;
2232  VkDeviceSize offsets[1024];
2233  FFVulkanShaderData *sd = get_shd_data(e, shd);
2234 
2235  if (s->extensions & FF_VK_EXT_SHADER_OBJECT) {
2236  VkShaderStageFlagBits stages = shd->stage;
2237  vk->CmdBindShadersEXT(e->buf, 1, &stages, &shd->object);
2238  } else {
2239  vk->CmdBindPipeline(e->buf, shd->bind_point, shd->pipeline);
2240  }
2241 
2242  if (sd->nb_descriptor_sets) {
2243  if (s->extensions & FF_VK_EXT_DESCRIPTOR_BUFFER) {
2244  for (int i = 0; i < sd->nb_descriptor_sets; i++)
2245  offsets[i] = shd->desc_set[i].singular ? 0 : shd->desc_set[i].aligned_size*e->idx;
2246 
2247  /* Bind descriptor buffers */
2248  vk->CmdBindDescriptorBuffersEXT(e->buf, sd->nb_descriptor_sets, sd->desc_bind);
2249  /* Binding offsets */
2250  vk->CmdSetDescriptorBufferOffsetsEXT(e->buf, shd->bind_point, shd->pipeline_layout,
2251  0, sd->nb_descriptor_sets,
2253  } else if (!shd->use_push) {
2254  vk->CmdBindDescriptorSets(e->buf, shd->bind_point, shd->pipeline_layout,
2255  0, sd->nb_descriptor_sets,
2256  &sd->desc_sets[e->idx*sd->nb_descriptor_sets],
2257  0, NULL);
2258  }
2259  }
2260 }
2261 
2263 {
2264  FFVulkanFunctions *vk = &s->vkfn;
2265 
2266  av_bprint_finalize(&shd->src, NULL);
2267 
2268 #if 0
2269  if (shd->shader.module)
2270  vk->DestroyShaderModule(s->hwctx->act_dev, shd->shader.module,
2271  s->hwctx->alloc);
2272 #endif
2273 
2274  if (shd->object)
2275  vk->DestroyShaderEXT(s->hwctx->act_dev, shd->object, s->hwctx->alloc);
2276  if (shd->pipeline)
2277  vk->DestroyPipeline(s->hwctx->act_dev, shd->pipeline, s->hwctx->alloc);
2278  if (shd->pipeline_layout)
2279  vk->DestroyPipelineLayout(s->hwctx->act_dev, shd->pipeline_layout,
2280  s->hwctx->alloc);
2281 
2282  for (int i = 0; i < shd->nb_descriptor_sets; i++) {
2283  FFVulkanDescriptorSet *set = &shd->desc_set[i];
2284  av_free(set->binding);
2285  av_free(set->binding_offset);
2286  }
2287 
2288  for (int i = 0; i < shd->nb_descriptor_sets; i++)
2289  if (shd->desc_layout[i])
2290  vk->DestroyDescriptorSetLayout(s->hwctx->act_dev, shd->desc_layout[i],
2291  s->hwctx->alloc);
2292 
2293  av_freep(&shd->desc_pool_size);
2294  av_freep(&shd->desc_layout);
2295  av_freep(&shd->desc_set);
2297  av_freep(&shd->push_consts);
2298  shd->push_consts_num = 0;
2299 }
2300 
2302 {
2303  av_freep(&s->query_props);
2304  av_freep(&s->qf_props);
2305  av_freep(&s->video_props);
2306  av_freep(&s->coop_mat_props);
2307 
2308  av_buffer_unref(&s->device_ref);
2309  av_buffer_unref(&s->frames_ref);
2310 }
2311 
2312 int ff_vk_init(FFVulkanContext *s, void *log_parent,
2313  AVBufferRef *device_ref, AVBufferRef *frames_ref)
2314 {
2315  int err;
2316 
2317  static const AVClass vulkan_context_class = {
2318  .class_name = "vk",
2319  .version = LIBAVUTIL_VERSION_INT,
2320  .parent_log_context_offset = offsetof(FFVulkanContext, log_parent),
2321  };
2322 
2323  memset(s, 0, sizeof(*s));
2324  s->log_parent = log_parent;
2325  s->class = &vulkan_context_class;
2326 
2327  if (frames_ref) {
2328  s->frames_ref = av_buffer_ref(frames_ref);
2329  if (!s->frames_ref)
2330  return AVERROR(ENOMEM);
2331 
2332  s->frames = (AVHWFramesContext *)s->frames_ref->data;
2333  s->hwfc = s->frames->hwctx;
2334 
2335  device_ref = s->frames->device_ref;
2336  }
2337 
2338  s->device_ref = av_buffer_ref(device_ref);
2339  if (!s->device_ref) {
2340  ff_vk_uninit(s);
2341  return AVERROR(ENOMEM);
2342  }
2343 
2344  s->device = (AVHWDeviceContext *)s->device_ref->data;
2345  s->hwctx = s->device->hwctx;
2346 
2347  s->extensions = ff_vk_extensions_to_mask(s->hwctx->enabled_dev_extensions,
2348  s->hwctx->nb_enabled_dev_extensions);
2349  s->extensions |= ff_vk_extensions_to_mask(s->hwctx->enabled_inst_extensions,
2350  s->hwctx->nb_enabled_inst_extensions);
2351 
2352  err = ff_vk_load_functions(s->device, &s->vkfn, s->extensions, 1, 1);
2353  if (err < 0) {
2354  ff_vk_uninit(s);
2355  return err;
2356  }
2357 
2358  err = ff_vk_load_props(s);
2359  if (err < 0) {
2360  ff_vk_uninit(s);
2361  return err;
2362  }
2363 
2364  return 0;
2365 }
FFVulkanShader::bind_point
VkPipelineBindPoint bind_point
Definition: vulkan.h:191
vulkan_loader.h
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:928
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
AVPixelFormat
AVPixelFormat
Pixel format.
Definition: pixfmt.h:71
name
it s the only field you need to keep assuming you have a context There is some magic you don t need to care about around this just let it vf default minimum maximum flags name is the option name
Definition: writing_filters.txt:88
ImageViewCtx::nb_views
int nb_views
Definition: vulkan.c:1297
AVERROR
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later. That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another. Frame references ownership and permissions
ff_comp_identity_map
const VkComponentMapping ff_comp_identity_map
Definition: vulkan.c:27
FFVkExecContext::frame_deps_alloc_size
unsigned int frame_deps_alloc_size
Definition: vulkan.h:134
ff_vk_shader_free
void ff_vk_shader_free(FFVulkanContext *s, FFVulkanShader *shd)
Free a shader.
Definition: vulkan.c:2262
ff_vk_shader_init
int ff_vk_shader_init(FFVulkanContext *s, FFVulkanShader *shd, const char *name, VkPipelineStageFlags stage, const char *extensions[], int nb_extensions, int lg_x, int lg_y, int lg_z, uint32_t required_subgroup_size)
Initialize a shader object, with a specific set of extensions, type+bind, local group size,...
Definition: vulkan.c:1430
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:243
AVBufferPool
The buffer pool.
Definition: buffer_internal.h:88
FFVkExecPool::contexts
FFVkExecContext * contexts
Definition: vulkan.h:242
FFVulkanDescriptorSetData
Definition: vulkan.h:221
FFVulkanShader::nb_desc_pool_size
int nb_desc_pool_size
Definition: vulkan.h:218
av_pix_fmt_desc_get
const AVPixFmtDescriptor * av_pix_fmt_desc_get(enum AVPixelFormat pix_fmt)
Definition: pixdesc.c:2965
pthread_mutex_init
static av_always_inline int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr)
Definition: os2threads.h:104
FFVulkanShaderData
Definition: vulkan.h:227
ARR_REALLOC
#define ARR_REALLOC(str, arr, alloc_s, cnt)
Definition: vulkan.c:594
FFVkExecContext::qf
int qf
Definition: vulkan.h:115
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:168
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:457
FFVulkanShaderData::shd
FFVulkanShader * shd
Definition: vulkan.h:229
descriptor_props::is_uniform
int is_uniform
Definition: vulkan.c:1772
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:762
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
FFVulkanShader::subgroup_info
VkPipelineShaderStageRequiredSubgroupSizeCreateInfo subgroup_info
Definition: vulkan.h:194
FFVulkanShader::pipeline
VkPipeline pipeline
Definition: vulkan.h:198
FFVkExecContext::sem_sig_alloc
unsigned int sem_sig_alloc
Definition: vulkan.h:142
FFVulkanShaderData::desc_bind
VkDescriptorBufferBindingInfoEXT * desc_bind
Definition: vulkan.h:234
FFVulkanShader::src
AVBPrint src
Definition: vulkan.h:184
alloc_data_buf
static AVBufferRef * alloc_data_buf(void *opaque, size_t size)
Definition: vulkan.c:1158
FFVulkanShader::use_push
int use_push
Definition: vulkan.h:216
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:225
TempSyncCtx::nb_sem
int nb_sem
Definition: vulkan.c:605
FFVkBuffer::address
VkDeviceAddress address
Definition: vulkan.h:92
FFVkExecContext::sem_wait
VkSemaphoreSubmitInfo * sem_wait
Definition: vulkan.h:137
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:2312
ff_vk_exec_get
FFVkExecContext * ff_vk_exec_get(FFVulkanContext *s, FFVkExecPool *pool)
Retrieve an execution pool.
Definition: vulkan.c:485
ff_vk_uninit
void ff_vk_uninit(FFVulkanContext *s)
Frees main context.
Definition: vulkan.c:2301
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_EXT_COOP_MATRIX
#define FF_VK_EXT_COOP_MATRIX
Definition: vulkan_functions.h:46
av_popcount
#define av_popcount
Definition: common.h:154
FFVkExecPool::query_pool
VkQueryPool query_pool
Definition: vulkan.h:249
FFVkExecPool::nb_reg_shd
int nb_reg_shd
Definition: vulkan.h:260
FFVulkanDescriptorSetData::desc_mem
uint8_t * desc_mem
Definition: vulkan.h:224
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:692
FFVulkanShaderData::desc_sets
VkDescriptorSet * desc_sets
Definition: vulkan.h:237
descriptor_props::type
const char * type
Definition: vulkan.c:1771
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:88
av_malloc
#define av_malloc(s)
Definition: tableprint_vlc.h:30
FFVkExecContext::lock
pthread_mutex_t lock
Definition: vulkan.h:110
ImageViewCtx
Definition: vulkan.c:1296
FFVkExecContext::frame_update_alloc_size
unsigned int frame_update_alloc_size
Definition: vulkan.h:162
av_pix_fmt_count_planes
int av_pix_fmt_count_planes(enum AVPixelFormat pix_fmt)
Definition: pixdesc.c:3005
FFVulkanShader::desc_layout
VkDescriptorSetLayout * desc_layout
Definition: vulkan.h:212
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:1015
ff_vk_find_struct
static const void * ff_vk_find_struct(const void *chain, VkStructureType stype)
Definition: vulkan.h:317
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:621
ff_vk_unmap_buffers
int ff_vk_unmap_buffers(FFVulkanContext *s, FFVkBuffer **buf, int nb_buffers, int flush)
Definition: vulkan.c:1097
ff_vk_shader_update_img_array
void ff_vk_shader_update_img_array(FFVulkanContext *s, FFVkExecContext *e, FFVulkanShader *shd, AVFrame *f, VkImageView *views, int set, int binding, VkImageLayout layout, VkSampler sampler)
Update a descriptor in a buffer with an image array.
Definition: vulkan.c:2205
AVVulkanFramesContext
Allocated as AVHWFramesContext.hwctx, used to set pool-specific options.
Definition: hwcontext_vulkan.h:213
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:253
ff_vk_shader_register_exec
int ff_vk_shader_register_exec(FFVulkanContext *s, FFVkExecPool *pool, FFVulkanShader *shd)
Register a shader with an exec pool.
Definition: vulkan.c:1902
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_shader_add_descriptor_set
int ff_vk_shader_add_descriptor_set(FFVulkanContext *s, FFVulkanShader *shd, FFVulkanDescriptorSetBinding *desc, int nb, int singular, int print_to_shader_only)
Add descriptor to a shader.
Definition: vulkan.c:1790
create_shader_module
static int create_shader_module(FFVulkanContext *s, FFVulkanShader *shd, VkShaderModule *mod, uint8_t *spirv, size_t spirv_len)
Definition: vulkan.c:1549
FFVkExecPool::query_statuses
int query_statuses
Definition: vulkan.h:252
descriptor_props::struct_size
size_t struct_size
Definition: vulkan.c:1770
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:171
init_descriptors
static int init_descriptors(FFVulkanContext *s, FFVulkanShader *shd)
Definition: vulkan.c:1651
init_pipeline_layout
static int init_pipeline_layout(FFVulkanContext *s, FFVulkanShader *shd)
Definition: vulkan.c:1523
avassert.h
FFVulkanDescriptorSetData::buf
FFVkBuffer buf
Definition: vulkan.h:223
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:209
FFVkExecContext::frame_deps
AVFrame ** frame_deps
Definition: vulkan.h:133
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:1023
FFVkExecContext::queue_family_dst
uint32_t * queue_family_dst
Definition: vulkan.h:158
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
FFVulkanShader::push_consts
VkPushConstantRange * push_consts
Definition: vulkan.h:204
av_fast_realloc
void * av_fast_realloc(void *ptr, unsigned int *size, size_t min_size)
Reallocate the given buffer if it is not large enough, otherwise do nothing.
Definition: mem.c:497
s
#define s(width, name)
Definition: cbs_vp9.c:198
ff_vk_exec_mirror_sem_value
int ff_vk_exec_mirror_sem_value(FFVulkanContext *s, FFVkExecContext *e, VkSemaphore *dst, uint64_t *dst_val, AVFrame *f)
Definition: vulkan.c:781
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:105
pix_fmt
static enum AVPixelFormat pix_fmt
Definition: demux_decode.c:41
FFVkExecContext::fence
VkFence fence
Definition: vulkan.h:122
update_set_descriptor
static void update_set_descriptor(FFVulkanContext *s, FFVkExecContext *e, FFVulkanShader *shd, int set, int bind_idx, int array_idx, VkDescriptorGetInfoEXT *desc_get_info, size_t desc_size)
Definition: vulkan.c:2028
ff_vk_exec_wait
void ff_vk_exec_wait(FFVulkanContext *s, FFVkExecContext *e)
Definition: vulkan.c:499
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:230
FFVkExecContext::nb_buf_deps
int nb_buf_deps
Definition: vulkan.h:129
FFVulkanShader::stage
VkPipelineStageFlags stage
Definition: vulkan.h:190
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:570
ff_vk_unmap_buffer
static int ff_vk_unmap_buffer(FFVulkanContext *s, FFVkBuffer *buf, int flush)
Definition: vulkan.h:477
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:1298
FFVkExecContext::frame_update
uint8_t * frame_update
Definition: vulkan.h:161
FFVkExecContext::query_idx
int query_idx
Definition: vulkan.h:125
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:254
FFVkExecContext::parent
const struct FFVkExecPool * parent
Definition: vulkan.h:109
if
if(ret)
Definition: filter_design.txt:179
FFVulkanShaderData::desc_set_buf
FFVulkanDescriptorSetData * desc_set_buf
Definition: vulkan.h:233
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:75
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:873
FFVkExecContext::sem_sig_val_dst_alloc
unsigned int sem_sig_val_dst_alloc
Definition: vulkan.h:146
descriptor_props::mem_quali
int mem_quali
Definition: vulkan.c:1773
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
FF_VK_EXT_SHADER_OBJECT
#define FF_VK_EXT_SHADER_OBJECT
Definition: vulkan_functions.h:48
FFVkExecContext::access_dst_alloc
unsigned int access_dst_alloc
Definition: vulkan.h:153
FFVulkanDescriptorSet::singular
int singular
Definition: vulkan.h:176
FFVkExecContext::sem_sig_cnt
int sem_sig_cnt
Definition: vulkan.h:143
TempSyncCtx::sem
VkSemaphore sem[]
Definition: vulkan.c:606
load_enabled_qfs
static void load_enabled_qfs(FFVulkanContext *s)
Definition: vulkan.c:87
TempSyncCtx
Definition: vulkan.c:604
flush
void(* flush)(AVBSFContext *ctx)
Definition: dts2pts.c:370
FFVkExecContext::qi
int qi
Definition: vulkan.h:116
FFVkExecContext::had_submission
int had_submission
Definition: vulkan.h:111
FFVkBuffer::size
size_t size
Definition: vulkan.h:91
descriptor_props::dim_needed
int dim_needed
Definition: vulkan.c:1774
FFVkExecPool::nb_queries
int nb_queries
Definition: vulkan.h:255
AV_PIX_FMT_BGR0
@ AV_PIX_FMT_BGR0
packed BGR 8:8:8, 32bpp, BGRXBGRX... X=unused/undefined
Definition: pixfmt.h:265
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:300
FFVkBuffer::mapped_mem
uint8_t * mapped_mem
Definition: vulkan.h:99
FFVulkanContext
Definition: vulkan.h:263
FFVulkanShader::nb_descriptor_sets
int nb_descriptor_sets
Definition: vulkan.h:209
ff_vk_count_images
static int ff_vk_count_images(AVVkFrame *f)
Definition: vulkan.h:308
FFVulkanShader::bound_buffer_indices
uint32_t * bound_buffer_indices
Definition: vulkan.h:213
AV_PIX_FMT_ABGR
@ AV_PIX_FMT_ABGR
packed ABGR 8:8:8:8, 32bpp, ABGRABGR...
Definition: pixfmt.h:101
init_compute_pipeline
static int init_compute_pipeline(FFVulkanContext *s, FFVulkanShader *shd, VkShaderModule mod, const char *entrypoint)
Definition: vulkan.c:1575
index
int index
Definition: gxfenc.c:90
FFVkExecContext::query_data
void * query_data
Definition: vulkan.h:124
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
vk_set_descriptor_image
static int vk_set_descriptor_image(FFVulkanContext *s, FFVulkanShader *shd, FFVkExecContext *e, int set, int bind, int offs, VkImageView view, VkImageLayout layout, VkSampler sampler)
Definition: vulkan.c:2074
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:155
destroy_imageviews
static void destroy_imageviews(void *opaque, uint8_t *data)
Definition: vulkan.c:1301
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:159
AVVkFrame::access
VkAccessFlagBits access[AV_NUM_DATA_POINTERS]
Updated after every barrier.
Definition: hwcontext_vulkan.h:331
ff_vk_shader_update_push_const
void ff_vk_shader_update_push_const(FFVulkanContext *s, FFVkExecContext *e, FFVulkanShader *shd, VkShaderStageFlagBits stage, int offset, size_t size, void *src)
Update push constant in a shader.
Definition: vulkan.c:2218
FFVulkanDescriptorSetBinding
Definition: vulkan.h:75
FFVulkanShaderData::nb_descriptor_sets
int nb_descriptor_sets
Definition: vulkan.h:230
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
FFVulkanShader::desc_pool_size
VkDescriptorPoolSize * desc_pool_size
Definition: vulkan.h:217
size
int size
Definition: twinvq_data.h:10344
AV_NUM_DATA_POINTERS
#define AV_NUM_DATA_POINTERS
Definition: frame.h:390
FF_VK_EXT_PUSH_DESCRIPTOR
#define FF_VK_EXT_PUSH_DESCRIPTOR
Definition: vulkan_functions.h:49
FFVkExecContext::nb_frame_deps
int nb_frame_deps
Definition: vulkan.h:135
FFVkQueueFamilyCtx
Definition: vulkan.h:102
FFVulkanShader
Definition: vulkan.h:179
FFVulkanShader::pipeline_layout
VkPipelineLayout pipeline_layout
Definition: vulkan.h:201
FFVkExecContext::sem_sig_val_dst_cnt
int sem_sig_val_dst_cnt
Definition: vulkan.h:147
update_set_pool_write
static void update_set_pool_write(FFVulkanContext *s, FFVkExecContext *e, FFVulkanShader *shd, int set, VkWriteDescriptorSet *write_info)
Definition: vulkan.c:2047
FFVkBuffer::flags
VkMemoryPropertyFlagBits flags
Definition: vulkan.h:90
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:107
line
Definition: graph2dot.c:48
ff_vk_shader_update_desc_buffer
int ff_vk_shader_update_desc_buffer(FFVulkanContext *s, FFVkExecContext *e, FFVulkanShader *shd, int set, int bind, int elem, FFVkBuffer *buf, VkDeviceSize offset, VkDeviceSize len, VkFormat fmt)
Update a descriptor in a buffer with a buffer.
Definition: vulkan.c:2139
AV_PIX_FMT_RGB0
@ AV_PIX_FMT_RGB0
packed RGB 8:8:8, 32bpp, RGBXRGBX... X=unused/undefined
Definition: pixfmt.h:263
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:1276
destroy_tmp_semaphores
static void destroy_tmp_semaphores(void *opaque, uint8_t *data)
Definition: vulkan.c:609
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:139
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:114
descriptor_props
Definition: vulkan.c:1769
ff_vk_exec_start
int ff_vk_exec_start(FFVulkanContext *s, FFVkExecContext *e)
Start/submit/wait an execution.
Definition: vulkan.c:508
FF_VK_EXT_RELAXED_EXTENDED_INSTR
#define FF_VK_EXT_RELAXED_EXTENDED_INSTR
Definition: vulkan_functions.h:50
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:256
FFVulkanShaderData::desc_pool
VkDescriptorPool desc_pool
Definition: vulkan.h:238
VkFormat
enum VkFormat VkFormat
Definition: hwcontext_stub.c:25
FFVulkanShader::push_consts_num
int push_consts_num
Definition: vulkan.h:205
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:1387
FFVkExecContext::layout_dst_alloc
unsigned int layout_dst_alloc
Definition: vulkan.h:156
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:1289
FFVkExecPool::reg_shd
FFVulkanShaderData * reg_shd
Definition: vulkan.h:259
FFMIN
#define FFMIN(a, b)
Definition: macros.h:49
ff_vk_shader_link
int ff_vk_shader_link(FFVulkanContext *s, FFVulkanShader *shd, uint8_t *spirv, size_t spirv_len, const char *entrypoint)
Link a shader into an executable.
Definition: vulkan.c:1715
FFVkBuffer::mem
VkDeviceMemory mem
Definition: vulkan.h:89
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
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:150
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:1135
av_calloc
void * av_calloc(size_t nmemb, size_t size)
Definition: mem.c:264
mod
static int mod(int a, int b)
Modulo operation with only positive remainders.
Definition: vf_v360.c:752
ff_vk_exec_bind_shader
void ff_vk_exec_bind_shader(FFVulkanContext *s, FFVkExecContext *e, FFVulkanShader *shd)
Bind a shader.
Definition: vulkan.c:2228
FFVulkanDescriptorSet::binding_offset
VkDeviceSize * binding_offset
Definition: vulkan.h:172
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:138
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
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:470
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:80
FFVulkanShader::name
const char * name
Definition: vulkan.h:181
AVHWFramesContext::hwctx
void * hwctx
The format-specific data, allocated and freed automatically along with this context.
Definition: hwcontext.h:150
FFVkExecPool
Definition: vulkan.h:241
FFVkExecContext::frame_locked
uint8_t * frame_locked
Definition: vulkan.h:149
FFVkExecPool::query_data
void * query_data
Definition: vulkan.h:250
descriptor_props::buf_content
int buf_content
Definition: vulkan.c:1775
FFVkExecContext::sem_sig
VkSemaphoreSubmitInfo * sem_sig
Definition: vulkan.h:141
av_bprintf
void av_bprintf(AVBPrint *buf, const char *fmt,...)
Definition: bprint.c:99
ff_vk_shader_add_push_const
int ff_vk_shader_add_push_const(FFVulkanShader *shd, int offset, int size, VkShaderStageFlagBits stage)
Add/update push constants for execution.
Definition: vulkan.c:1223
FF_VK_EXT_DESCRIPTOR_BUFFER
#define FF_VK_EXT_DESCRIPTOR_BUFFER
Definition: vulkan_functions.h:43
FFVkExecContext::buf
VkCommandBuffer buf
Definition: vulkan.h:119
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:104
FFVulkanShader::desc_set
FFVulkanDescriptorSet * desc_set
Definition: vulkan.h:208
free_data_buf
static void free_data_buf(void *opaque, uint8_t *data)
Definition: vulkan.c:1150
FFVulkanShader::object
VkShaderEXT object
Definition: vulkan.h:197
ref
static int ref[MAX_W *MAX_W]
Definition: jpeg2000dwt.c:112
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:246
AVPixFmtDescriptor
Descriptor that unambiguously describes how the bits of a pixel are stored in the up to 4 data planes...
Definition: pixdesc.h:69
ff_vk_shader_print
void ff_vk_shader_print(void *ctx, FFVulkanShader *shd, int prio)
Output the shader code as logging data, with a specific priority.
Definition: vulkan.c:1501
av_free
#define av_free(p)
Definition: tableprint_vlc.h:33
ff_vk_exec_discard_deps
void ff_vk_exec_discard_deps(FFVulkanContext *s, FFVkExecContext *e)
Definition: vulkan.c:544
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:1244
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:130
FFVkExecContext::buf_deps
AVBufferRef ** buf_deps
Definition: vulkan.h:128
FFVkBuffer
Definition: vulkan.h:87
ff_vk_exec_submit
int ff_vk_exec_submit(FFVulkanContext *s, FFVkExecContext *e)
Definition: vulkan.c:807
flags
#define flags(name, subs,...)
Definition: cbs_av1.c:482
FF_VK_EXT_DEBUG_UTILS
#define FF_VK_EXT_DEBUG_UTILS
Definition: vulkan_functions.h:36
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:256
FFVulkanDescriptorSet
Definition: vulkan.h:165
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:1313
FFVkExecPool::query_results
int query_results
Definition: vulkan.h:251
create_shader_object
static int create_shader_object(FFVulkanContext *s, FFVulkanShader *shd, uint8_t *spirv, size_t spirv_len, const char *entrypoint)
Definition: vulkan.c:1610
FFVkExecContext::sem_sig_val_dst
uint64_t ** sem_sig_val_dst
Definition: vulkan.h:145
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
get_shd_data
static FFVulkanShaderData * get_shd_data(FFVkExecContext *e, FFVulkanShader *shd)
Definition: vulkan.c:2019
CASE
#define CASE(VAL)
FFVulkanFunctions
Definition: vulkan_functions.h:263
FFVkExecPool::pool_size
int pool_size
Definition: vulkan.h:247
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:245
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:1171
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:1050
FFVkExecContext::idx
uint32_t idx
Definition: vulkan.h:108
src
#define src
Definition: vp8dsp.c:248
FFVkQueueFamilyCtx::queue_family
int queue_family
Definition: vulkan.h:103
pthread_mutex_lock
#define pthread_mutex_lock(a)
Definition: ffprobe.c:78
FFVulkanShader::lg_size
int lg_size[3]
Definition: vulkan.h:187
FFVkExecContext::access_dst
VkAccessFlagBits * access_dst
Definition: vulkan.h:152