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_11 = (VkPhysicalDeviceVulkan11Properties) {
134  .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_PROPERTIES,
135  .pNext = &s->driver_props,
136  };
137  s->props = (VkPhysicalDeviceProperties2) {
138  .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2,
139  .pNext = &s->props_11,
140  };
141 
142  s->atomic_float_feats = (VkPhysicalDeviceShaderAtomicFloatFeaturesEXT) {
143  .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_ATOMIC_FLOAT_FEATURES_EXT,
144  };
145  s->feats_12 = (VkPhysicalDeviceVulkan12Features) {
146  .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES,
147  .pNext = &s->atomic_float_feats,
148  };
149  s->feats = (VkPhysicalDeviceFeatures2) {
150  .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2,
151  .pNext = &s->feats_12,
152  };
153 
154  vk->GetPhysicalDeviceProperties2(s->hwctx->phys_dev, &s->props);
155  vk->GetPhysicalDeviceMemoryProperties(s->hwctx->phys_dev, &s->mprops);
156  vk->GetPhysicalDeviceFeatures2(s->hwctx->phys_dev, &s->feats);
157 
159 
160  if (s->qf_props)
161  return 0;
162 
163  vk->GetPhysicalDeviceQueueFamilyProperties2(s->hwctx->phys_dev, &s->tot_nb_qfs, NULL);
164 
165  s->qf_props = av_calloc(s->tot_nb_qfs, sizeof(*s->qf_props));
166  if (!s->qf_props)
167  return AVERROR(ENOMEM);
168 
169  s->query_props = av_calloc(s->tot_nb_qfs, sizeof(*s->query_props));
170  if (!s->qf_props) {
171  av_freep(&s->qf_props);
172  return AVERROR(ENOMEM);
173  }
174 
175  s->video_props = av_calloc(s->tot_nb_qfs, sizeof(*s->video_props));
176  if (!s->video_props) {
177  av_freep(&s->qf_props);
178  av_freep(&s->query_props);
179  return AVERROR(ENOMEM);
180  }
181 
182  for (uint32_t i = 0; i < s->tot_nb_qfs; i++) {
183  s->query_props[i] = (VkQueueFamilyQueryResultStatusPropertiesKHR) {
184  .sType = VK_STRUCTURE_TYPE_QUEUE_FAMILY_QUERY_RESULT_STATUS_PROPERTIES_KHR,
185  };
186  s->video_props[i] = (VkQueueFamilyVideoPropertiesKHR) {
187  .sType = VK_STRUCTURE_TYPE_QUEUE_FAMILY_VIDEO_PROPERTIES_KHR,
188  .pNext = &s->query_props[i],
189  };
190  s->qf_props[i] = (VkQueueFamilyProperties2) {
191  .sType = VK_STRUCTURE_TYPE_QUEUE_FAMILY_PROPERTIES_2,
192  .pNext = &s->video_props[i],
193  };
194  }
195 
196  vk->GetPhysicalDeviceQueueFamilyProperties2(s->hwctx->phys_dev, &s->tot_nb_qfs, s->qf_props);
197 
198  if (s->extensions & FF_VK_EXT_COOP_MATRIX) {
199  vk->GetPhysicalDeviceCooperativeMatrixPropertiesKHR(s->hwctx->phys_dev,
200  &s->coop_mat_props_nb, NULL);
201 
202  if (s->coop_mat_props_nb) {
203  s->coop_mat_props = av_malloc_array(s->coop_mat_props_nb,
204  sizeof(VkCooperativeMatrixPropertiesKHR));
205  for (int i = 0; i < s->coop_mat_props_nb; i++) {
206  s->coop_mat_props[i] = (VkCooperativeMatrixPropertiesKHR) {
207  .sType = VK_STRUCTURE_TYPE_COOPERATIVE_MATRIX_PROPERTIES_KHR,
208  };
209  }
210 
211  vk->GetPhysicalDeviceCooperativeMatrixPropertiesKHR(s->hwctx->phys_dev,
212  &s->coop_mat_props_nb,
213  s->coop_mat_props);
214  }
215  }
216 
217  return 0;
218 }
219 
221  VkQueueFlagBits dev_family,
222  VkVideoCodecOperationFlagBitsKHR vid_ops)
223 {
224  for (int i = 0; i < s->hwctx->nb_qf; i++) {
225  if ((s->hwctx->qf[i].flags & dev_family) &&
226  (s->hwctx->qf[i].video_caps & vid_ops) == vid_ops) {
227  return &s->hwctx->qf[i];
228  }
229  }
230  return NULL;
231 }
232 
234 {
235  FFVulkanFunctions *vk = &s->vkfn;
236 
237  for (int i = 0; i < pool->pool_size; i++) {
238  FFVkExecContext *e = &pool->contexts[i];
239 
240  if (e->fence) {
241  if (e->had_submission)
242  vk->WaitForFences(s->hwctx->act_dev, 1, &e->fence, VK_TRUE, UINT64_MAX);
243  vk->DestroyFence(s->hwctx->act_dev, e->fence, s->hwctx->alloc);
244  }
245 
247 
248  av_free(e->frame_deps);
250  av_free(e->buf_deps);
252  av_free(e->layout_dst);
253  av_free(e->access_dst);
254  av_free(e->frame_update);
255  av_free(e->frame_locked);
256  av_free(e->sem_sig);
258  av_free(e->sem_wait);
259  }
260 
261  /* Free shader-specific data */
262  for (int i = 0; i < pool->nb_reg_shd; i++) {
263  FFVulkanShaderData *sd = &pool->reg_shd[i];
264 
265  if (s->extensions & FF_VK_EXT_DESCRIPTOR_BUFFER) {
266  for (int j = 0; j < sd->nb_descriptor_sets; j++) {
267  FFVulkanDescriptorSetData *set_data = &sd->desc_set_buf[j];
268  if (set_data->buf.mem)
269  ff_vk_unmap_buffer(s, &set_data->buf, 0);
270  ff_vk_free_buf(s, &set_data->buf);
271  }
272  }
273 
274  if (sd->desc_pool)
275  vk->DestroyDescriptorPool(s->hwctx->act_dev, sd->desc_pool,
276  s->hwctx->alloc);
277 
278  av_freep(&sd->desc_set_buf);
279  av_freep(&sd->desc_bind);
280  av_freep(&sd->desc_sets);
281  }
282 
283  if (pool->cmd_bufs)
284  vk->FreeCommandBuffers(s->hwctx->act_dev, pool->cmd_buf_pool,
285  pool->pool_size, pool->cmd_bufs);
286  if (pool->cmd_buf_pool)
287  vk->DestroyCommandPool(s->hwctx->act_dev, pool->cmd_buf_pool, s->hwctx->alloc);
288  if (pool->query_pool)
289  vk->DestroyQueryPool(s->hwctx->act_dev, pool->query_pool, s->hwctx->alloc);
290 
291  av_free(pool->query_data);
292  av_free(pool->cmd_bufs);
293  av_free(pool->contexts);
294 }
295 
297  FFVkExecPool *pool, int nb_contexts,
298  int nb_queries, VkQueryType query_type, int query_64bit,
299  const void *query_create_pnext)
300 {
301  int err;
302  VkResult ret;
303  FFVulkanFunctions *vk = &s->vkfn;
304 
305  VkCommandPoolCreateInfo cqueue_create;
306  VkCommandBufferAllocateInfo cbuf_create;
307 
308  const VkQueryPoolVideoEncodeFeedbackCreateInfoKHR *ef = NULL;
309 
310  atomic_init(&pool->idx, 0);
311 
312  if (query_type == VK_QUERY_TYPE_VIDEO_ENCODE_FEEDBACK_KHR) {
313  ef = ff_vk_find_struct(query_create_pnext,
314  VK_STRUCTURE_TYPE_QUERY_POOL_VIDEO_ENCODE_FEEDBACK_CREATE_INFO_KHR);
315  if (!ef)
316  return AVERROR(EINVAL);
317  }
318 
319  /* Create command pool */
320  cqueue_create = (VkCommandPoolCreateInfo) {
321  .sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
322  .flags = VK_COMMAND_POOL_CREATE_TRANSIENT_BIT |
323  VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,
324  .queueFamilyIndex = qf->idx,
325  };
326  ret = vk->CreateCommandPool(s->hwctx->act_dev, &cqueue_create,
327  s->hwctx->alloc, &pool->cmd_buf_pool);
328  if (ret != VK_SUCCESS) {
329  av_log(s, AV_LOG_ERROR, "Command pool creation failure: %s\n",
330  ff_vk_ret2str(ret));
331  err = AVERROR_EXTERNAL;
332  goto fail;
333  }
334 
335  /* Allocate space for command buffers */
336  pool->cmd_bufs = av_malloc(nb_contexts*sizeof(*pool->cmd_bufs));
337  if (!pool->cmd_bufs) {
338  err = AVERROR(ENOMEM);
339  goto fail;
340  }
341 
342  /* Allocate command buffer */
343  cbuf_create = (VkCommandBufferAllocateInfo) {
344  .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
345  .level = VK_COMMAND_BUFFER_LEVEL_PRIMARY,
346  .commandPool = pool->cmd_buf_pool,
347  .commandBufferCount = nb_contexts,
348  };
349  ret = vk->AllocateCommandBuffers(s->hwctx->act_dev, &cbuf_create,
350  pool->cmd_bufs);
351  if (ret != VK_SUCCESS) {
352  av_log(s, AV_LOG_ERROR, "Command buffer alloc failure: %s\n",
353  ff_vk_ret2str(ret));
354  err = AVERROR_EXTERNAL;
355  goto fail;
356  }
357 
358  /* Query pool */
359  if (nb_queries) {
360  VkQueryPoolCreateInfo query_pool_info = {
361  .sType = VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO,
362  .pNext = query_create_pnext,
363  .queryType = query_type,
364  .queryCount = nb_queries*nb_contexts,
365  };
366  ret = vk->CreateQueryPool(s->hwctx->act_dev, &query_pool_info,
367  s->hwctx->alloc, &pool->query_pool);
368  if (ret != VK_SUCCESS) {
369  av_log(s, AV_LOG_ERROR, "Query pool alloc failure: %s\n",
370  ff_vk_ret2str(ret));
371  err = AVERROR_EXTERNAL;
372  goto fail;
373  }
374 
375  pool->nb_queries = nb_queries;
376  pool->query_status_stride = 1 + 1; /* One result, one status by default */
377  pool->query_results = nb_queries;
378  pool->query_statuses = nb_queries;
379 
380  /* Video encode quieries produce two results per query */
381  if (query_type == VK_QUERY_TYPE_VIDEO_ENCODE_FEEDBACK_KHR) {
382  int nb_results = av_popcount(ef->encodeFeedbackFlags);
383  pool->query_status_stride = nb_results + 1;
384  pool->query_results *= nb_results;
385  } else if (query_type == VK_QUERY_TYPE_RESULT_STATUS_ONLY_KHR) {
386  pool->query_status_stride = 1;
387  pool->query_results = 0;
388  }
389 
390  pool->qd_size = (pool->query_results + pool->query_statuses)*(query_64bit ? 8 : 4);
391 
392  /* Allocate space for the query data */
393  pool->query_data = av_calloc(nb_contexts, pool->qd_size);
394  if (!pool->query_data) {
395  err = AVERROR(ENOMEM);
396  goto fail;
397  }
398  }
399 
400  /* Allocate space for the contexts */
401  pool->contexts = av_calloc(nb_contexts, sizeof(*pool->contexts));
402  if (!pool->contexts) {
403  err = AVERROR(ENOMEM);
404  goto fail;
405  }
406 
407  pool->pool_size = nb_contexts;
408 
409  /* Init contexts */
410  for (int i = 0; i < pool->pool_size; i++) {
411  FFVkExecContext *e = &pool->contexts[i];
412  VkFenceCreateInfo fence_create = {
413  .sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,
414  .flags = VK_FENCE_CREATE_SIGNALED_BIT,
415  };
416 
417  /* Fence */
418  ret = vk->CreateFence(s->hwctx->act_dev, &fence_create, s->hwctx->alloc,
419  &e->fence);
420  if (ret != VK_SUCCESS) {
421  av_log(s, AV_LOG_ERROR, "Failed to create submission fence: %s\n",
422  ff_vk_ret2str(ret));
423  return AVERROR_EXTERNAL;
424  }
425 
426  e->idx = i;
427  e->parent = pool;
428 
429  /* Query data */
430  e->query_data = ((uint8_t *)pool->query_data) + pool->qd_size*i;
431  e->query_idx = nb_queries*i;
432 
433  /* Command buffer */
434  e->buf = pool->cmd_bufs[i];
435 
436  /* Queue index distribution */
437  e->qi = i % qf->num;
438  e->qf = qf->idx;
439  vk->GetDeviceQueue(s->hwctx->act_dev, qf->idx, e->qi, &e->queue);
440  }
441 
442  return 0;
443 
444 fail:
445  ff_vk_exec_pool_free(s, pool);
446  return err;
447 }
448 
450  void **data, VkQueryResultFlagBits flags)
451 {
452  FFVulkanFunctions *vk = &s->vkfn;
453  const FFVkExecPool *pool = e->parent;
454  VkQueryResultFlags qf = flags & ~(VK_QUERY_RESULT_64_BIT |
455  VK_QUERY_RESULT_WITH_STATUS_BIT_KHR);
456 
457  if (!e->query_data) {
458  av_log(s, AV_LOG_ERROR, "Requested a query with a NULL query_data pointer!\n");
459  return VK_INCOMPLETE;
460  }
461 
462  qf |= pool->query_64bit ?
463  VK_QUERY_RESULT_64_BIT : 0x0;
464  qf |= pool->query_statuses ?
465  VK_QUERY_RESULT_WITH_STATUS_BIT_KHR : 0x0;
466 
467  if (data)
468  *data = e->query_data;
469 
470  return vk->GetQueryPoolResults(s->hwctx->act_dev, pool->query_pool,
471  e->query_idx,
472  pool->nb_queries,
473  pool->qd_size, e->query_data,
474  pool->qd_size, qf);
475 }
476 
478 {
479  return &pool->contexts[atomic_fetch_add(&pool->idx, 1) % pool->pool_size];
480 }
481 
483 {
484  FFVulkanFunctions *vk = &s->vkfn;
485  vk->WaitForFences(s->hwctx->act_dev, 1, &e->fence, VK_TRUE, UINT64_MAX);
487 }
488 
490 {
491  VkResult ret;
492  FFVulkanFunctions *vk = &s->vkfn;
493  const FFVkExecPool *pool = e->parent;
494 
495  VkCommandBufferBeginInfo cmd_start = {
496  .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
497  .flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,
498  };
499 
500  /* Wait for the fence to be signalled */
501  vk->WaitForFences(s->hwctx->act_dev, 1, &e->fence, VK_TRUE, UINT64_MAX);
502  vk->ResetFences(s->hwctx->act_dev, 1, &e->fence);
503 
504  /* Discard queue dependencies */
506 
507  ret = vk->BeginCommandBuffer(e->buf, &cmd_start);
508  if (ret != VK_SUCCESS) {
509  av_log(s, AV_LOG_ERROR, "Failed to start command recoding: %s\n",
510  ff_vk_ret2str(ret));
511  return AVERROR_EXTERNAL;
512  }
513 
514  if (pool->nb_queries)
515  vk->CmdResetQueryPool(e->buf, pool->query_pool,
516  e->query_idx, pool->nb_queries);
517 
518  return 0;
519 }
520 
522 {
523  for (int j = 0; j < e->nb_buf_deps; j++)
524  av_buffer_unref(&e->buf_deps[j]);
525  e->nb_buf_deps = 0;
526 
527  for (int j = 0; j < e->nb_sw_frame_deps; j++)
529  e->nb_sw_frame_deps = 0;
530 
531  for (int j = 0; j < e->nb_frame_deps; j++) {
532  AVFrame *f = e->frame_deps[j];
533  if (e->frame_locked[j]) {
534  AVHWFramesContext *hwfc = (AVHWFramesContext *)f->hw_frames_ctx->data;
535  AVVulkanFramesContext *vkfc = hwfc->hwctx;
536  AVVkFrame *vkf = (AVVkFrame *)f->data[0];
537  vkfc->unlock_frame(hwfc, vkf);
538  e->frame_locked[j] = 0;
539  }
540  e->frame_update[j] = 0;
541  if (f->buf[0])
542  av_frame_free(&e->frame_deps[j]);
543  }
544  e->nb_frame_deps = 0;
545 
546  e->sem_wait_cnt = 0;
547  e->sem_sig_cnt = 0;
548  e->sem_sig_val_dst_cnt = 0;
549 }
550 
552  AVBufferRef **deps, int nb_deps, int ref)
553 {
555  (e->nb_buf_deps + nb_deps) * sizeof(*dst));
556  if (!dst) {
558  return AVERROR(ENOMEM);
559  }
560 
561  e->buf_deps = dst;
562 
563  for (int i = 0; i < nb_deps; i++) {
564  e->buf_deps[e->nb_buf_deps] = ref ? av_buffer_ref(deps[i]) : deps[i];
565  if (!e->buf_deps[e->nb_buf_deps]) {
567  return AVERROR(ENOMEM);
568  }
569  e->nb_buf_deps++;
570  }
571 
572  return 0;
573 }
574 
576  AVFrame *f)
577 {
579  (e->nb_sw_frame_deps + 1) * sizeof(*dst));
580  if (!dst) {
582  return AVERROR(ENOMEM);
583  }
584 
585  e->sw_frame_deps = dst;
586 
588  if (!e->sw_frame_deps[e->nb_sw_frame_deps]) {
590  return AVERROR(ENOMEM);
591  }
592 
593  e->nb_sw_frame_deps++;
594 
595  return 0;
596 }
597 
598 #define ARR_REALLOC(str, arr, alloc_s, cnt) \
599  do { \
600  arr = av_fast_realloc(str->arr, alloc_s, (cnt + 1)*sizeof(*arr)); \
601  if (!arr) { \
602  ff_vk_exec_discard_deps(s, e); \
603  return AVERROR(ENOMEM); \
604  } \
605  str->arr = arr; \
606  } while (0)
607 
608 typedef struct TempSyncCtx {
609  int nb_sem;
610  VkSemaphore sem[];
611 } TempSyncCtx;
612 
613 static void destroy_tmp_semaphores(void *opaque, uint8_t *data)
614 {
615  FFVulkanContext *s = opaque;
616  FFVulkanFunctions *vk = &s->vkfn;
617  TempSyncCtx *ts = (TempSyncCtx *)data;
618 
619  for (int i = 0; i < ts->nb_sem; i++)
620  vk->DestroySemaphore(s->hwctx->act_dev, ts->sem[i], s->hwctx->alloc);
621 
622  av_free(ts);
623 }
624 
626  VkSemaphore *sem, int nb,
627  VkPipelineStageFlagBits2 stage,
628  int wait)
629 {
630  int err;
631  size_t buf_size;
632  AVBufferRef *buf;
633  TempSyncCtx *ts;
634  FFVulkanFunctions *vk = &s->vkfn;
635 
636  /* Do not transfer ownership if we're signalling a binary semaphore,
637  * since we're probably exporting it. */
638  if (!wait) {
639  for (int i = 0; i < nb; i++) {
640  VkSemaphoreSubmitInfo *sem_sig;
641  ARR_REALLOC(e, sem_sig, &e->sem_sig_alloc, e->sem_sig_cnt);
642 
643  e->sem_sig[e->sem_sig_cnt++] = (VkSemaphoreSubmitInfo) {
644  .sType = VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO,
645  .semaphore = sem[i],
646  .stageMask = stage,
647  };
648  }
649 
650  return 0;
651  }
652 
653  buf_size = sizeof(*ts) + sizeof(VkSemaphore)*nb;
654  ts = av_mallocz(buf_size);
655  if (!ts) {
656  err = AVERROR(ENOMEM);
657  goto fail;
658  }
659 
660  memcpy(ts->sem, sem, nb*sizeof(*sem));
661  ts->nb_sem = nb;
662 
663  buf = av_buffer_create((uint8_t *)ts, buf_size, destroy_tmp_semaphores, s, 0);
664  if (!buf) {
665  av_free(ts);
666  err = AVERROR(ENOMEM);
667  goto fail;
668  }
669 
670  err = ff_vk_exec_add_dep_buf(s, e, &buf, 1, 0);
671  if (err < 0) {
672  av_buffer_unref(&buf);
673  return err;
674  }
675 
676  for (int i = 0; i < nb; i++) {
677  VkSemaphoreSubmitInfo *sem_wait;
679 
680  e->sem_wait[e->sem_wait_cnt++] = (VkSemaphoreSubmitInfo) {
681  .sType = VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO,
682  .semaphore = sem[i],
683  .stageMask = stage,
684  };
685  }
686 
687  return 0;
688 
689 fail:
690  for (int i = 0; i < nb; i++)
691  vk->DestroySemaphore(s->hwctx->act_dev, sem[i], s->hwctx->alloc);
692 
693  return err;
694 }
695 
697  VkPipelineStageFlagBits2 wait_stage,
698  VkPipelineStageFlagBits2 signal_stage)
699 {
700  uint8_t *frame_locked;
701  uint8_t *frame_update;
702  AVFrame **frame_deps;
703  VkImageLayout *layout_dst;
704  uint32_t *queue_family_dst;
705  VkAccessFlagBits *access_dst;
706 
707  AVHWFramesContext *hwfc = (AVHWFramesContext *)f->hw_frames_ctx->data;
708  AVVulkanFramesContext *vkfc = hwfc->hwctx;
709  AVVkFrame *vkf = (AVVkFrame *)f->data[0];
710  int nb_images = ff_vk_count_images(vkf);
711 
712  /* Don't add duplicates */
713  for (int i = 0; i < e->nb_frame_deps; i++)
714  if (e->frame_deps[i]->data[0] == f->data[0])
715  return 1;
716 
717  ARR_REALLOC(e, layout_dst, &e->layout_dst_alloc, e->nb_frame_deps);
718  ARR_REALLOC(e, queue_family_dst, &e->queue_family_dst_alloc, e->nb_frame_deps);
719  ARR_REALLOC(e, access_dst, &e->access_dst_alloc, e->nb_frame_deps);
720 
721  ARR_REALLOC(e, frame_locked, &e->frame_locked_alloc_size, e->nb_frame_deps);
722  ARR_REALLOC(e, frame_update, &e->frame_update_alloc_size, e->nb_frame_deps);
723  ARR_REALLOC(e, frame_deps, &e->frame_deps_alloc_size, e->nb_frame_deps);
724 
725  e->frame_deps[e->nb_frame_deps] = f->buf[0] ? av_frame_clone(f) : f;
726  if (!e->frame_deps[e->nb_frame_deps]) {
728  return AVERROR(ENOMEM);
729  }
730 
731  vkfc->lock_frame(hwfc, vkf);
732  e->frame_locked[e->nb_frame_deps] = 1;
733  e->frame_update[e->nb_frame_deps] = 0;
734  e->nb_frame_deps++;
735 
736  for (int i = 0; i < nb_images; i++) {
737  VkSemaphoreSubmitInfo *sem_wait;
738  VkSemaphoreSubmitInfo *sem_sig;
739  uint64_t **sem_sig_val_dst;
740 
742  ARR_REALLOC(e, sem_sig, &e->sem_sig_alloc, e->sem_sig_cnt);
743  ARR_REALLOC(e, sem_sig_val_dst, &e->sem_sig_val_dst_alloc, e->sem_sig_val_dst_cnt);
744 
745  e->sem_wait[e->sem_wait_cnt++] = (VkSemaphoreSubmitInfo) {
746  .sType = VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO,
747  .semaphore = vkf->sem[i],
748  .value = vkf->sem_value[i],
749  .stageMask = wait_stage,
750  };
751 
752  e->sem_sig[e->sem_sig_cnt++] = (VkSemaphoreSubmitInfo) {
753  .sType = VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO,
754  .semaphore = vkf->sem[i],
755  .value = vkf->sem_value[i] + 1,
756  .stageMask = signal_stage,
757  };
758 
759  e->sem_sig_val_dst[e->sem_sig_val_dst_cnt] = &vkf->sem_value[i];
760  e->sem_sig_val_dst_cnt++;
761  }
762 
763  return 0;
764 }
765 
767  VkImageMemoryBarrier2 *bar, uint32_t *nb_img_bar)
768 {
769  int i;
770  for (i = 0; i < e->nb_frame_deps; i++)
771  if (e->frame_deps[i]->data[0] == f->data[0])
772  break;
773  av_assert0(i < e->nb_frame_deps);
774 
775  /* Don't update duplicates */
776  if (nb_img_bar && !e->frame_update[i])
777  (*nb_img_bar)++;
778 
779  e->queue_family_dst[i] = bar->dstQueueFamilyIndex;
780  e->access_dst[i] = bar->dstAccessMask;
781  e->layout_dst[i] = bar->newLayout;
782  e->frame_update[i] = 1;
783 }
784 
786  VkSemaphore *dst, uint64_t *dst_val,
787  AVFrame *f)
788 {
789  uint64_t **sem_sig_val_dst;
790  AVVkFrame *vkf = (AVVkFrame *)f->data[0];
791 
792  /* Reject unknown frames */
793  int i;
794  for (i = 0; i < e->nb_frame_deps; i++)
795  if (e->frame_deps[i]->data[0] == f->data[0])
796  break;
797  if (i == e->nb_frame_deps)
798  return AVERROR(EINVAL);
799 
800  ARR_REALLOC(e, sem_sig_val_dst, &e->sem_sig_val_dst_alloc, e->sem_sig_val_dst_cnt);
801 
802  *dst = vkf->sem[0];
803  *dst_val = vkf->sem_value[0];
804 
805  e->sem_sig_val_dst[e->sem_sig_val_dst_cnt] = dst_val;
806  e->sem_sig_val_dst_cnt++;
807 
808  return 0;
809 }
810 
812 {
813  VkResult ret;
814  FFVulkanFunctions *vk = &s->vkfn;
815  VkCommandBufferSubmitInfo cmd_buf_info = (VkCommandBufferSubmitInfo) {
816  .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_SUBMIT_INFO,
817  .commandBuffer = e->buf,
818  };
819  VkSubmitInfo2 submit_info = (VkSubmitInfo2) {
820  .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO_2,
821  .pCommandBufferInfos = &cmd_buf_info,
822  .commandBufferInfoCount = 1,
823  .pWaitSemaphoreInfos = e->sem_wait,
824  .waitSemaphoreInfoCount = e->sem_wait_cnt,
825  .pSignalSemaphoreInfos = e->sem_sig,
826  .signalSemaphoreInfoCount = e->sem_sig_cnt,
827  };
828 
829  ret = vk->EndCommandBuffer(e->buf);
830  if (ret != VK_SUCCESS) {
831  av_log(s, AV_LOG_ERROR, "Unable to finish command buffer: %s\n",
832  ff_vk_ret2str(ret));
834  return AVERROR_EXTERNAL;
835  }
836 
837  s->hwctx->lock_queue(s->device, e->qf, e->qi);
838  ret = vk->QueueSubmit2(e->queue, 1, &submit_info, e->fence);
839  s->hwctx->unlock_queue(s->device, e->qf, e->qi);
840 
841  if (ret != VK_SUCCESS) {
842  av_log(s, AV_LOG_ERROR, "Unable to submit command buffer: %s\n",
843  ff_vk_ret2str(ret));
845  return AVERROR_EXTERNAL;
846  }
847 
848  for (int i = 0; i < e->sem_sig_val_dst_cnt; i++)
849  *e->sem_sig_val_dst[i] += 1;
850 
851  /* Unlock all frames */
852  for (int j = 0; j < e->nb_frame_deps; j++) {
853  if (e->frame_locked[j]) {
854  AVFrame *f = e->frame_deps[j];
855  AVHWFramesContext *hwfc = (AVHWFramesContext *)f->hw_frames_ctx->data;
856  AVVulkanFramesContext *vkfc = hwfc->hwctx;
857  AVVkFrame *vkf = (AVVkFrame *)f->data[0];
858 
859  if (e->frame_update[j]) {
860  int nb_images = ff_vk_count_images(vkf);
861  for (int i = 0; i < nb_images; i++) {
862  vkf->layout[i] = e->layout_dst[j];
863  vkf->access[i] = e->access_dst[j];
864  vkf->queue_family[i] = e->queue_family_dst[j];
865  }
866  }
867  vkfc->unlock_frame(hwfc, vkf);
868  e->frame_locked[j] = 0;
869  }
870  }
871 
872  e->had_submission = 1;
873 
874  return 0;
875 }
876 
877 int ff_vk_alloc_mem(FFVulkanContext *s, VkMemoryRequirements *req,
878  VkMemoryPropertyFlagBits req_flags, void *alloc_extension,
879  VkMemoryPropertyFlagBits *mem_flags, VkDeviceMemory *mem)
880 {
881  VkResult ret;
882  int index = -1;
883  FFVulkanFunctions *vk = &s->vkfn;
884 
885  VkMemoryAllocateInfo alloc_info = {
886  .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
887  .pNext = alloc_extension,
888  };
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 = flags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT ?
943  FFALIGN(size, s->props.properties.limits.minMemoryMapAlignment) :
944  size,
945  };
946 
947  VkMemoryAllocateFlagsInfo alloc_flags = {
948  .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_FLAGS_INFO,
949  .flags = VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT,
950  };
951  VkBufferMemoryRequirementsInfo2 req_desc = {
952  .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_REQUIREMENTS_INFO_2,
953  };
954  VkMemoryDedicatedAllocateInfo ded_alloc = {
955  .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO,
956  .pNext = alloc_pNext,
957  };
958  VkMemoryDedicatedRequirements ded_req = {
959  .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS,
960  };
961  VkMemoryRequirements2 req = {
962  .sType = VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2,
963  .pNext = &ded_req,
964  };
965 
966  av_log(s, AV_LOG_DEBUG, "Creating a buffer of %"SIZE_SPECIFIER" bytes, "
967  "usage: 0x%x, flags: 0x%x\n",
968  size, usage, flags);
969 
970  ret = vk->CreateBuffer(s->hwctx->act_dev, &buf_spawn, s->hwctx->alloc, &buf->buf);
971  if (ret != VK_SUCCESS) {
972  av_log(s, AV_LOG_ERROR, "Failed to create buffer: %s\n",
973  ff_vk_ret2str(ret));
974  return AVERROR_EXTERNAL;
975  }
976 
977  req_desc.buffer = buf->buf;
978 
979  vk->GetBufferMemoryRequirements2(s->hwctx->act_dev, &req_desc, &req);
980 
981  /* In case the implementation prefers/requires dedicated allocation */
982  use_ded_mem = ded_req.prefersDedicatedAllocation |
983  ded_req.requiresDedicatedAllocation;
984  if (use_ded_mem) {
985  ded_alloc.buffer = buf->buf;
986  ded_alloc.pNext = alloc_pNext;
987  alloc_pNext = &ded_alloc;
988  }
989 
990  if (usage & VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT) {
991  alloc_flags.pNext = alloc_pNext;
992  alloc_pNext = &alloc_flags;
993  }
994 
995  err = ff_vk_alloc_mem(s, &req.memoryRequirements, flags, alloc_pNext,
996  &buf->flags, &buf->mem);
997  if (err)
998  return err;
999 
1000  ret = vk->BindBufferMemory(s->hwctx->act_dev, buf->buf, buf->mem, 0);
1001  if (ret != VK_SUCCESS) {
1002  av_log(s, AV_LOG_ERROR, "Failed to bind memory to buffer: %s\n",
1003  ff_vk_ret2str(ret));
1004  return AVERROR_EXTERNAL;
1005  }
1006 
1007  if (usage & VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT) {
1008  VkBufferDeviceAddressInfo address_info = {
1009  .sType = VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO,
1010  .buffer = buf->buf,
1011  };
1012  buf->address = vk->GetBufferDeviceAddress(s->hwctx->act_dev, &address_info);
1013  }
1014 
1015  buf->size = size;
1016 
1017  return 0;
1018 }
1019 
1020 static void destroy_avvkbuf(void *opaque, uint8_t *data)
1021 {
1022  FFVulkanContext *s = opaque;
1023  FFVkBuffer *buf = (FFVkBuffer *)data;
1024  ff_vk_free_buf(s, buf);
1025  av_free(buf);
1026 }
1027 
1029  void *pNext, void *alloc_pNext,
1030  VkBufferUsageFlags usage, VkMemoryPropertyFlagBits flags)
1031 {
1032  int err;
1033  AVBufferRef *buf;
1034  FFVkBuffer *vkb = av_mallocz(sizeof(*vkb));
1035  if (!vkb)
1036  return AVERROR(ENOMEM);
1037 
1038  err = ff_vk_create_buf(s, vkb, size, pNext, alloc_pNext, usage, flags);
1039  if (err < 0) {
1040  av_free(vkb);
1041  return err;
1042  }
1043 
1044  buf = av_buffer_create((uint8_t *)vkb, sizeof(*vkb), destroy_avvkbuf, s, 0);
1045  if (!buf) {
1046  destroy_avvkbuf(s, (uint8_t *)vkb);
1047  return AVERROR(ENOMEM);
1048  }
1049 
1050  *ref = buf;
1051 
1052  return 0;
1053 }
1054 
1055 int ff_vk_map_buffers(FFVulkanContext *s, FFVkBuffer **buf, uint8_t *mem[],
1056  int nb_buffers, int invalidate)
1057 {
1058  VkResult ret;
1059  FFVulkanFunctions *vk = &s->vkfn;
1060  VkMappedMemoryRange inval_list[64];
1061  int inval_count = 0;
1062 
1063  for (int i = 0; i < nb_buffers; i++) {
1064  void *dst;
1065  ret = vk->MapMemory(s->hwctx->act_dev, buf[i]->mem, 0,
1066  VK_WHOLE_SIZE, 0, &dst);
1067  if (ret != VK_SUCCESS) {
1068  av_log(s, AV_LOG_ERROR, "Failed to map buffer memory: %s\n",
1069  ff_vk_ret2str(ret));
1070  return AVERROR_EXTERNAL;
1071  }
1072  mem[i] = buf[i]->mapped_mem = dst;
1073  }
1074 
1075  if (!invalidate)
1076  return 0;
1077 
1078  for (int i = 0; i < nb_buffers; i++) {
1079  const VkMappedMemoryRange ival_buf = {
1080  .sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,
1081  .memory = buf[i]->mem,
1082  .size = VK_WHOLE_SIZE,
1083  };
1084  if (buf[i]->flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)
1085  continue;
1086  inval_list[inval_count++] = ival_buf;
1087  }
1088 
1089  if (inval_count) {
1090  ret = vk->InvalidateMappedMemoryRanges(s->hwctx->act_dev, inval_count,
1091  inval_list);
1092  if (ret != VK_SUCCESS) {
1093  av_log(s, AV_LOG_ERROR, "Failed to invalidate memory: %s\n",
1094  ff_vk_ret2str(ret));
1095  return AVERROR_EXTERNAL;
1096  }
1097  }
1098 
1099  return 0;
1100 }
1101 
1102 int ff_vk_unmap_buffers(FFVulkanContext *s, FFVkBuffer **buf, int nb_buffers,
1103  int flush)
1104 {
1105  int err = 0;
1106  VkResult ret;
1107  FFVulkanFunctions *vk = &s->vkfn;
1108  VkMappedMemoryRange flush_list[64];
1109  int flush_count = 0;
1110 
1111  if (flush) {
1112  for (int i = 0; i < nb_buffers; i++) {
1113  const VkMappedMemoryRange flush_buf = {
1114  .sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,
1115  .memory = buf[i]->mem,
1116  .size = VK_WHOLE_SIZE,
1117  };
1118  if (buf[i]->flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)
1119  continue;
1120  flush_list[flush_count++] = flush_buf;
1121  }
1122  }
1123 
1124  if (flush_count) {
1125  ret = vk->FlushMappedMemoryRanges(s->hwctx->act_dev, flush_count,
1126  flush_list);
1127  if (ret != VK_SUCCESS) {
1128  av_log(s, AV_LOG_ERROR, "Failed to flush memory: %s\n",
1129  ff_vk_ret2str(ret));
1130  err = AVERROR_EXTERNAL; /* We still want to try to unmap them */
1131  }
1132  }
1133 
1134  for (int i = 0; i < nb_buffers; i++) {
1135  vk->UnmapMemory(s->hwctx->act_dev, buf[i]->mem);
1136  buf[i]->mapped_mem = NULL;
1137  }
1138 
1139  return err;
1140 }
1141 
1143 {
1144  FFVulkanFunctions *vk = &s->vkfn;
1145 
1146  if (!buf || !s->hwctx)
1147  return;
1148 
1149  if (buf->mapped_mem)
1150  ff_vk_unmap_buffer(s, buf, 0);
1151  if (buf->buf != VK_NULL_HANDLE)
1152  vk->DestroyBuffer(s->hwctx->act_dev, buf->buf, s->hwctx->alloc);
1153  if (buf->mem != VK_NULL_HANDLE)
1154  vk->FreeMemory(s->hwctx->act_dev, buf->mem, s->hwctx->alloc);
1155 }
1156 
1157 static void free_data_buf(void *opaque, uint8_t *data)
1158 {
1159  FFVulkanContext *ctx = opaque;
1160  FFVkBuffer *buf = (FFVkBuffer *)data;
1161  ff_vk_free_buf(ctx, buf);
1162  av_free(data);
1163 }
1164 
1165 static AVBufferRef *alloc_data_buf(void *opaque, size_t size)
1166 {
1167  AVBufferRef *ref;
1168  uint8_t *buf = av_mallocz(size);
1169  if (!buf)
1170  return NULL;
1171 
1172  ref = av_buffer_create(buf, size, free_data_buf, opaque, 0);
1173  if (!ref)
1174  av_free(buf);
1175  return ref;
1176 }
1177 
1179  AVBufferRef **buf, VkBufferUsageFlags usage,
1180  void *create_pNext, size_t size,
1181  VkMemoryPropertyFlagBits mem_props)
1182 {
1183  int err;
1184  AVBufferRef *ref;
1185  FFVkBuffer *data;
1186 
1187  *buf = NULL;
1188 
1189  if (!(*buf_pool)) {
1190  *buf_pool = av_buffer_pool_init2(sizeof(FFVkBuffer), ctx,
1191  alloc_data_buf, NULL);
1192  if (!(*buf_pool))
1193  return AVERROR(ENOMEM);
1194  }
1195 
1196  *buf = ref = av_buffer_pool_get(*buf_pool);
1197  if (!ref)
1198  return AVERROR(ENOMEM);
1199 
1200  data = (FFVkBuffer *)ref->data;
1201  data->stage = VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT;
1202  data->access = VK_ACCESS_2_NONE;
1203 
1204  if (data->size >= size)
1205  return 0;
1206 
1208  memset(data, 0, sizeof(*data));
1209 
1210  err = ff_vk_create_buf(ctx, data, size,
1211  create_pNext, NULL, usage,
1212  mem_props);
1213  if (err < 0) {
1214  av_buffer_unref(&ref);
1215  *buf = NULL;
1216  return err;
1217  }
1218 
1219  if (mem_props & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) {
1220  err = ff_vk_map_buffer(ctx, data, &data->mapped_mem, 0);
1221  if (err < 0) {
1222  av_buffer_unref(&ref);
1223  *buf = NULL;
1224  return err;
1225  }
1226  }
1227 
1228  return 0;
1229 }
1230 
1232  VkShaderStageFlagBits stage)
1233 {
1234  VkPushConstantRange *pc;
1235 
1237  sizeof(*shd->push_consts),
1238  shd->push_consts_num + 1);
1239  if (!shd->push_consts)
1240  return AVERROR(ENOMEM);
1241 
1242  pc = &shd->push_consts[shd->push_consts_num++];
1243  memset(pc, 0, sizeof(*pc));
1244 
1245  pc->stageFlags = stage;
1246  pc->offset = offset;
1247  pc->size = size;
1248 
1249  return 0;
1250 }
1251 
1252 int ff_vk_init_sampler(FFVulkanContext *s, VkSampler *sampler,
1253  int unnorm_coords, VkFilter filt)
1254 {
1255  VkResult ret;
1256  FFVulkanFunctions *vk = &s->vkfn;
1257 
1258  VkSamplerCreateInfo sampler_info = {
1259  .sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,
1260  .magFilter = filt,
1261  .minFilter = sampler_info.magFilter,
1262  .mipmapMode = unnorm_coords ? VK_SAMPLER_MIPMAP_MODE_NEAREST :
1263  VK_SAMPLER_MIPMAP_MODE_LINEAR,
1264  .addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
1265  .addressModeV = sampler_info.addressModeU,
1266  .addressModeW = sampler_info.addressModeU,
1267  .anisotropyEnable = VK_FALSE,
1268  .compareOp = VK_COMPARE_OP_NEVER,
1269  .borderColor = VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK,
1270  .unnormalizedCoordinates = unnorm_coords,
1271  };
1272 
1273  ret = vk->CreateSampler(s->hwctx->act_dev, &sampler_info,
1274  s->hwctx->alloc, sampler);
1275  if (ret != VK_SUCCESS) {
1276  av_log(s, AV_LOG_ERROR, "Unable to init sampler: %s\n",
1277  ff_vk_ret2str(ret));
1278  return AVERROR_EXTERNAL;
1279  }
1280 
1281  return 0;
1282 }
1283 
1284 VkImageAspectFlags ff_vk_aspect_flag(AVFrame *f, int p)
1285 {
1286  AVVkFrame *vkf = (AVVkFrame *)f->data[0];
1287  AVHWFramesContext *hwfc = (AVHWFramesContext *)f->hw_frames_ctx->data;
1288  int nb_images = ff_vk_count_images(vkf);
1289  int nb_planes = av_pix_fmt_count_planes(hwfc->sw_format);
1290 
1291  static const VkImageAspectFlags plane_aspect[] = { VK_IMAGE_ASPECT_PLANE_0_BIT,
1292  VK_IMAGE_ASPECT_PLANE_1_BIT,
1293  VK_IMAGE_ASPECT_PLANE_2_BIT, };
1294 
1295  if (ff_vk_mt_is_np_rgb(hwfc->sw_format) || (nb_planes == nb_images))
1296  return VK_IMAGE_ASPECT_COLOR_BIT;
1297 
1298  return plane_aspect[p];
1299 }
1300 
1302 {
1318  return 1;
1319  return 0;
1320 }
1321 
1323  enum FFVkShaderRepFormat rep_fmt)
1324 {
1325  switch (pix_fmt) {
1326  case AV_PIX_FMT_RGBA:
1327  case AV_PIX_FMT_BGRA:
1328  case AV_PIX_FMT_RGB24:
1329  case AV_PIX_FMT_BGR24:
1330  case AV_PIX_FMT_BGR0:
1331  case AV_PIX_FMT_RGB0:
1332  case AV_PIX_FMT_RGB565:
1333  case AV_PIX_FMT_BGR565:
1334  case AV_PIX_FMT_UYVA:
1335  case AV_PIX_FMT_YUYV422:
1336  case AV_PIX_FMT_UYVY422: {
1337  const char *rep_tab[] = {
1338  [FF_VK_REP_NATIVE] = "rgba8ui",
1339  [FF_VK_REP_FLOAT] = "rgba8",
1340  [FF_VK_REP_INT] = "rgba8i",
1341  [FF_VK_REP_UINT] = "rgba8ui",
1342  };
1343  return rep_tab[rep_fmt];
1344  }
1345  case AV_PIX_FMT_X2RGB10:
1346  case AV_PIX_FMT_X2BGR10:
1347  case AV_PIX_FMT_Y210:
1348  case AV_PIX_FMT_XV30: {
1349  const char *rep_tab[] = {
1350  [FF_VK_REP_NATIVE] = "rgb10_a2ui",
1351  [FF_VK_REP_FLOAT] = "rgb10_a2",
1352  [FF_VK_REP_INT] = NULL,
1353  [FF_VK_REP_UINT] = "rgb10_a2ui",
1354  };
1355  return rep_tab[rep_fmt];
1356  }
1357  case AV_PIX_FMT_RGB48:
1358  case AV_PIX_FMT_RGBA64:
1359  case AV_PIX_FMT_Y212:
1360  case AV_PIX_FMT_Y216:
1361  case AV_PIX_FMT_XV36:
1362  case AV_PIX_FMT_XV48: {
1363  const char *rep_tab[] = {
1364  [FF_VK_REP_NATIVE] = "rgba16ui",
1365  [FF_VK_REP_FLOAT] = "rgba16",
1366  [FF_VK_REP_INT] = "rgba16i",
1367  [FF_VK_REP_UINT] = "rgba16ui",
1368  };
1369  return rep_tab[rep_fmt];
1370  }
1371  case AV_PIX_FMT_RGBF32:
1372  case AV_PIX_FMT_RGBAF32: {
1373  const char *rep_tab[] = {
1374  [FF_VK_REP_NATIVE] = "rgba32f",
1375  [FF_VK_REP_FLOAT] = "rgba32f",
1376  [FF_VK_REP_INT] = "rgba32i",
1377  [FF_VK_REP_UINT] = "rgba32ui",
1378  };
1379  return rep_tab[rep_fmt];
1380  }
1381  case AV_PIX_FMT_RGB96:
1382  case AV_PIX_FMT_RGBA128: {
1383  const char *rep_tab[] = {
1384  [FF_VK_REP_NATIVE] = "rgba32ui",
1385  [FF_VK_REP_FLOAT] = NULL,
1386  [FF_VK_REP_INT] = "rgba32i",
1387  [FF_VK_REP_UINT] = "rgba32ui",
1388  };
1389  return rep_tab[rep_fmt];
1390  }
1391  case AV_PIX_FMT_GRAY8:
1392  case AV_PIX_FMT_GBRAP:
1393  case AV_PIX_FMT_YUV420P:
1394  case AV_PIX_FMT_YUV422P:
1395  case AV_PIX_FMT_YUV444P: {
1396  const char *rep_tab[] = {
1397  [FF_VK_REP_NATIVE] = "r8ui",
1398  [FF_VK_REP_FLOAT] = "r8",
1399  [FF_VK_REP_INT] = "r8i",
1400  [FF_VK_REP_UINT] = "r8ui",
1401  };
1402  return rep_tab[rep_fmt];
1403  };
1404  case AV_PIX_FMT_GRAY10:
1405  case AV_PIX_FMT_GRAY12:
1406  case AV_PIX_FMT_GRAY14:
1407  case AV_PIX_FMT_GRAY16:
1408  case AV_PIX_FMT_GBRAP10:
1409  case AV_PIX_FMT_GBRAP12:
1410  case AV_PIX_FMT_GBRAP14:
1411  case AV_PIX_FMT_GBRAP16:
1412  case AV_PIX_FMT_GBRP10:
1413  case AV_PIX_FMT_GBRP12:
1414  case AV_PIX_FMT_GBRP14:
1415  case AV_PIX_FMT_GBRP16:
1416  case AV_PIX_FMT_YUV420P10:
1417  case AV_PIX_FMT_YUV420P12:
1418  case AV_PIX_FMT_YUV420P16:
1419  case AV_PIX_FMT_YUV422P10:
1420  case AV_PIX_FMT_YUV422P12:
1421  case AV_PIX_FMT_YUV422P16:
1422  case AV_PIX_FMT_YUV444P10:
1423  case AV_PIX_FMT_YUV444P12:
1424  case AV_PIX_FMT_YUV444P16: {
1425  const char *rep_tab[] = {
1426  [FF_VK_REP_NATIVE] = "r16ui",
1427  [FF_VK_REP_FLOAT] = "r16f",
1428  [FF_VK_REP_INT] = "r16i",
1429  [FF_VK_REP_UINT] = "r16ui",
1430  };
1431  return rep_tab[rep_fmt];
1432  };
1433  case AV_PIX_FMT_GRAYF32:
1434  case AV_PIX_FMT_GBRPF32:
1435  case AV_PIX_FMT_GBRAPF32: {
1436  const char *rep_tab[] = {
1437  [FF_VK_REP_NATIVE] = "r32f",
1438  [FF_VK_REP_FLOAT] = "r32f",
1439  [FF_VK_REP_INT] = "r32i",
1440  [FF_VK_REP_UINT] = "r32ui",
1441  };
1442  return rep_tab[rep_fmt];
1443  };
1444  case AV_PIX_FMT_NV12:
1445  case AV_PIX_FMT_NV16:
1446  case AV_PIX_FMT_NV24: {
1447  const char *rep_tab[] = {
1448  [FF_VK_REP_NATIVE] = "rg8ui",
1449  [FF_VK_REP_FLOAT] = "rg8",
1450  [FF_VK_REP_INT] = "rg8i",
1451  [FF_VK_REP_UINT] = "rg8ui",
1452  };
1453  return rep_tab[rep_fmt];
1454  };
1455  case AV_PIX_FMT_P010:
1456  case AV_PIX_FMT_P210:
1457  case AV_PIX_FMT_P410: {
1458  const char *rep_tab[] = {
1459  [FF_VK_REP_NATIVE] = "rgb10_a2ui",
1460  [FF_VK_REP_FLOAT] = "rgb10_a2",
1461  [FF_VK_REP_INT] = NULL,
1462  [FF_VK_REP_UINT] = "rgb10_a2ui",
1463  };
1464  return rep_tab[rep_fmt];
1465  };
1466  case AV_PIX_FMT_P012:
1467  case AV_PIX_FMT_P016:
1468  case AV_PIX_FMT_P212:
1469  case AV_PIX_FMT_P216:
1470  case AV_PIX_FMT_P412:
1471  case AV_PIX_FMT_P416: {
1472  const char *rep_tab[] = {
1473  [FF_VK_REP_NATIVE] = "rg16ui",
1474  [FF_VK_REP_FLOAT] = "rg16",
1475  [FF_VK_REP_INT] = "rg16i",
1476  [FF_VK_REP_UINT] = "rg16ui",
1477  };
1478  return rep_tab[rep_fmt];
1479  };
1480  default:
1481  return "rgba32f";
1482  }
1483 }
1484 
1485 typedef struct ImageViewCtx {
1487  VkImageView views[];
1488 } ImageViewCtx;
1489 
1490 static void destroy_imageviews(void *opaque, uint8_t *data)
1491 {
1492  FFVulkanContext *s = opaque;
1493  FFVulkanFunctions *vk = &s->vkfn;
1494  ImageViewCtx *iv = (ImageViewCtx *)data;
1495 
1496  for (int i = 0; i < iv->nb_views; i++)
1497  vk->DestroyImageView(s->hwctx->act_dev, iv->views[i], s->hwctx->alloc);
1498 
1499  av_free(iv);
1500 }
1501 
1503 {
1504 #define REPS_FMT(fmt) \
1505  [FF_VK_REP_NATIVE] = fmt ## _UINT, \
1506  [FF_VK_REP_FLOAT] = fmt ## _UNORM, \
1507  [FF_VK_REP_INT] = fmt ## _SINT, \
1508  [FF_VK_REP_UINT] = fmt ## _UINT,
1509 
1510 #define REPS_FMT_PACK(fmt, num) \
1511  [FF_VK_REP_NATIVE] = fmt ## _UINT_PACK ## num, \
1512  [FF_VK_REP_FLOAT] = fmt ## _UNORM_PACK ## num, \
1513  [FF_VK_REP_INT] = fmt ## _SINT_PACK ## num, \
1514  [FF_VK_REP_UINT] = fmt ## _UINT_PACK ## num,
1515 
1516  const VkFormat fmts_map[][4] = {
1517  { REPS_FMT_PACK(VK_FORMAT_A2B10G10R10, 32) },
1518  { REPS_FMT_PACK(VK_FORMAT_A2R10G10B10, 32) },
1519  {
1520  VK_FORMAT_B5G6R5_UNORM_PACK16,
1521  VK_FORMAT_B5G6R5_UNORM_PACK16,
1522  VK_FORMAT_UNDEFINED,
1523  VK_FORMAT_UNDEFINED,
1524  },
1525  {
1526  VK_FORMAT_R5G6B5_UNORM_PACK16,
1527  VK_FORMAT_R5G6B5_UNORM_PACK16,
1528  VK_FORMAT_UNDEFINED,
1529  VK_FORMAT_UNDEFINED,
1530  },
1531  { REPS_FMT(VK_FORMAT_B8G8R8) },
1532  { REPS_FMT(VK_FORMAT_B8G8R8A8) },
1533  { REPS_FMT(VK_FORMAT_R8) },
1534  { REPS_FMT(VK_FORMAT_R8G8) },
1535  { REPS_FMT(VK_FORMAT_R8G8B8) },
1536  { REPS_FMT(VK_FORMAT_R8G8B8A8) },
1537  { REPS_FMT(VK_FORMAT_R16) },
1538  { REPS_FMT(VK_FORMAT_R16G16) },
1539  { REPS_FMT(VK_FORMAT_R16G16B16) },
1540  { REPS_FMT(VK_FORMAT_R16G16B16A16) },
1541  {
1542  VK_FORMAT_R32_SFLOAT,
1543  VK_FORMAT_R32_SFLOAT,
1544  VK_FORMAT_UNDEFINED,
1545  VK_FORMAT_UNDEFINED,
1546  },
1547  {
1548  VK_FORMAT_R32G32B32_SFLOAT,
1549  VK_FORMAT_R32G32B32_SFLOAT,
1550  VK_FORMAT_UNDEFINED,
1551  VK_FORMAT_UNDEFINED,
1552  },
1553  {
1554  VK_FORMAT_R32G32B32A32_SFLOAT,
1555  VK_FORMAT_R32G32B32A32_SFLOAT,
1556  VK_FORMAT_UNDEFINED,
1557  VK_FORMAT_UNDEFINED,
1558  },
1559  {
1560  VK_FORMAT_R32G32B32_UINT,
1561  VK_FORMAT_UNDEFINED,
1562  VK_FORMAT_R32G32B32_SINT,
1563  VK_FORMAT_R32G32B32_UINT,
1564  },
1565  {
1566  VK_FORMAT_R32G32B32A32_UINT,
1567  VK_FORMAT_UNDEFINED,
1568  VK_FORMAT_R32G32B32A32_SINT,
1569  VK_FORMAT_R32G32B32A32_UINT,
1570  },
1571  };
1572 #undef REPS_FMT_PACK
1573 #undef REPS_FMT
1574 
1575  if (fmt == VK_FORMAT_UNDEFINED)
1576  return VK_FORMAT_UNDEFINED;
1577 
1578  for (int i = 0; i < FF_ARRAY_ELEMS(fmts_map); i++) {
1579  if (fmts_map[i][FF_VK_REP_NATIVE] == fmt ||
1580  fmts_map[i][FF_VK_REP_FLOAT] == fmt ||
1581  fmts_map[i][FF_VK_REP_INT] == fmt ||
1582  fmts_map[i][FF_VK_REP_UINT] == fmt)
1583  return fmts_map[i][rep_fmt];
1584  }
1585 
1586  return VK_FORMAT_UNDEFINED;
1587 }
1588 
1590  VkImageView views[AV_NUM_DATA_POINTERS],
1591  AVFrame *f, enum FFVkShaderRepFormat rep_fmt)
1592 {
1593  int err;
1594  VkResult ret;
1595  AVBufferRef *buf;
1596  FFVulkanFunctions *vk = &s->vkfn;
1597  AVHWFramesContext *hwfc = (AVHWFramesContext *)f->hw_frames_ctx->data;
1598  AVVulkanFramesContext *vkfc = hwfc->hwctx;
1599  const VkFormat *rep_fmts = av_vkfmt_from_pixfmt(hwfc->sw_format);
1600  AVVkFrame *vkf = (AVVkFrame *)f->data[0];
1601  const int nb_images = ff_vk_count_images(vkf);
1602  const int nb_planes = av_pix_fmt_count_planes(hwfc->sw_format);
1603 
1604  ImageViewCtx *iv;
1605  const size_t buf_size = sizeof(*iv) + nb_planes*sizeof(VkImageView);
1606  iv = av_mallocz(buf_size);
1607  if (!iv)
1608  return AVERROR(ENOMEM);
1609 
1610  for (int i = 0; i < nb_planes; i++) {
1611  VkImageViewUsageCreateInfo view_usage_info = {
1612  .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO,
1613  .usage = vkfc->usage &
1614  (~(VK_IMAGE_USAGE_VIDEO_ENCODE_SRC_BIT_KHR |
1615  VK_IMAGE_USAGE_VIDEO_DECODE_DST_BIT_KHR)),
1616  };
1617  VkImageViewCreateInfo view_create_info = {
1618  .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
1619  .pNext = &view_usage_info,
1620  .image = vkf->img[FFMIN(i, nb_images - 1)],
1621  .viewType = VK_IMAGE_VIEW_TYPE_2D,
1622  .format = map_fmt_to_rep(rep_fmts[i], rep_fmt),
1623  .components = ff_comp_identity_map,
1624  .subresourceRange = {
1625  .aspectMask = ff_vk_aspect_flag(f, i),
1626  .levelCount = 1,
1627  .layerCount = 1,
1628  },
1629  };
1630  if (view_create_info.format == VK_FORMAT_UNDEFINED) {
1631  av_log(s, AV_LOG_ERROR, "Unable to find a compatible representation "
1632  "of format %i and mode %i\n",
1633  rep_fmts[i], rep_fmt);
1634  err = AVERROR(EINVAL);
1635  goto fail;
1636  }
1637 
1638  ret = vk->CreateImageView(s->hwctx->act_dev, &view_create_info,
1639  s->hwctx->alloc, &iv->views[i]);
1640  if (ret != VK_SUCCESS) {
1641  av_log(s, AV_LOG_ERROR, "Failed to create imageview: %s\n",
1642  ff_vk_ret2str(ret));
1643  err = AVERROR_EXTERNAL;
1644  goto fail;
1645  }
1646 
1647  iv->nb_views++;
1648  }
1649 
1650  buf = av_buffer_create((uint8_t *)iv, buf_size, destroy_imageviews, s, 0);
1651  if (!buf) {
1652  err = AVERROR(ENOMEM);
1653  goto fail;
1654  }
1655 
1656  /* Add to queue dependencies */
1657  err = ff_vk_exec_add_dep_buf(s, e, &buf, 1, 0);
1658  if (err < 0)
1659  av_buffer_unref(&buf);
1660 
1661  memcpy(views, iv->views, nb_planes*sizeof(*views));
1662 
1663  return err;
1664 
1665 fail:
1666  for (int i = 0; i < iv->nb_views; i++)
1667  vk->DestroyImageView(s->hwctx->act_dev, iv->views[i], s->hwctx->alloc);
1668  av_free(iv);
1669  return err;
1670 }
1671 
1673  AVFrame *pic, VkImageMemoryBarrier2 *bar, int *nb_bar,
1674  VkPipelineStageFlags src_stage,
1675  VkPipelineStageFlags dst_stage,
1676  VkAccessFlagBits new_access,
1677  VkImageLayout new_layout,
1678  uint32_t new_qf)
1679 {
1680  int found = -1;
1681  AVVkFrame *vkf = (AVVkFrame *)pic->data[0];
1682  const int nb_images = ff_vk_count_images(vkf);
1683  for (int i = 0; i < e->nb_frame_deps; i++)
1684  if (e->frame_deps[i]->data[0] == pic->data[0]) {
1685  if (e->frame_update[i])
1686  found = i;
1687  break;
1688  }
1689 
1690  for (int i = 0; i < nb_images; i++) {
1691  bar[*nb_bar] = (VkImageMemoryBarrier2) {
1692  .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2,
1693  .pNext = NULL,
1694  .srcStageMask = src_stage,
1695  .dstStageMask = dst_stage,
1696  .srcAccessMask = found >= 0 ? e->access_dst[found] : vkf->access[i],
1697  .dstAccessMask = new_access,
1698  .oldLayout = found >= 0 ? e->layout_dst[found] : vkf->layout[0],
1699  .newLayout = new_layout,
1700  .srcQueueFamilyIndex = found >= 0 ? e->queue_family_dst[found] : vkf->queue_family[0],
1701  .dstQueueFamilyIndex = new_qf,
1702  .image = vkf->img[i],
1703  .subresourceRange = (VkImageSubresourceRange) {
1704  .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
1705  .layerCount = 1,
1706  .levelCount = 1,
1707  },
1708  };
1709  *nb_bar += 1;
1710  }
1711 
1712  ff_vk_exec_update_frame(s, e, pic, &bar[*nb_bar - nb_images], NULL);
1713 }
1714 
1716  VkPipelineStageFlags stage,
1717  const char *extensions[], int nb_extensions,
1718  int lg_x, int lg_y, int lg_z,
1719  uint32_t required_subgroup_size)
1720 {
1722 
1723  shd->name = name;
1724  shd->stage = stage;
1725  shd->lg_size[0] = lg_x;
1726  shd->lg_size[1] = lg_y;
1727  shd->lg_size[2] = lg_z;
1728 
1729  switch (shd->stage) {
1730  case VK_SHADER_STAGE_ANY_HIT_BIT_KHR:
1731  case VK_SHADER_STAGE_CALLABLE_BIT_KHR:
1732  case VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR:
1733  case VK_SHADER_STAGE_INTERSECTION_BIT_KHR:
1734  case VK_SHADER_STAGE_MISS_BIT_KHR:
1735  case VK_SHADER_STAGE_RAYGEN_BIT_KHR:
1736  shd->bind_point = VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR;
1737  break;
1738  case VK_SHADER_STAGE_COMPUTE_BIT:
1739  shd->bind_point = VK_PIPELINE_BIND_POINT_COMPUTE;
1740  break;
1741  default:
1742  shd->bind_point = VK_PIPELINE_BIND_POINT_GRAPHICS;
1743  break;
1744  };
1745 
1746  if (required_subgroup_size) {
1747  shd->subgroup_info.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_REQUIRED_SUBGROUP_SIZE_CREATE_INFO;
1748  shd->subgroup_info.requiredSubgroupSize = required_subgroup_size;
1749  }
1750 
1751  av_bprintf(&shd->src, "/* %s shader: %s */\n",
1752  (stage == VK_SHADER_STAGE_TASK_BIT_EXT ||
1753  stage == VK_SHADER_STAGE_MESH_BIT_EXT) ?
1754  "Mesh" :
1755  (shd->bind_point == VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR) ?
1756  "Raytrace" :
1757  (shd->bind_point == VK_PIPELINE_BIND_POINT_COMPUTE) ?
1758  "Compute" : "Graphics",
1759  name);
1760  GLSLF(0, #version %i ,460);
1761  GLSLC(0, );
1762 
1763  /* Common utilities */
1764  GLSLC(0, #define IS_WITHIN(v1, v2) ((v1.x < v2.x) && (v1.y < v2.y)) );
1765  GLSLC(0, );
1766  GLSLC(0, #extension GL_EXT_scalar_block_layout : require );
1767  GLSLC(0, #extension GL_EXT_shader_explicit_arithmetic_types : require );
1768  GLSLC(0, #extension GL_EXT_control_flow_attributes : require );
1769  if ((s->extensions & FF_VK_EXT_DEBUG_UTILS) &&
1770  (s->extensions & FF_VK_EXT_RELAXED_EXTENDED_INSTR)) {
1771  GLSLC(0, #extension GL_EXT_debug_printf : require );
1772  GLSLC(0, #define DEBUG );
1773  }
1774 
1775  if (stage == VK_SHADER_STAGE_TASK_BIT_EXT ||
1776  stage == VK_SHADER_STAGE_MESH_BIT_EXT)
1777  GLSLC(0, #extension GL_EXT_mesh_shader : require );
1778 
1779  for (int i = 0; i < nb_extensions; i++)
1780  GLSLF(0, #extension %s : %s ,extensions[i], "require");
1781  GLSLC(0, );
1782 
1783  GLSLF(0, layout (local_size_x = %i, local_size_y = %i, local_size_z = %i) in;
1784  , shd->lg_size[0], shd->lg_size[1], shd->lg_size[2]);
1785  GLSLC(0, );
1786 
1787  return 0;
1788 }
1789 
1790 void ff_vk_shader_print(void *ctx, FFVulkanShader *shd, int prio)
1791 {
1792  int line = 0;
1793  const char *p = shd->src.str;
1794  const char *start = p;
1795  const size_t len = strlen(p);
1796 
1797  AVBPrint buf;
1799 
1800  for (int i = 0; i < len; i++) {
1801  if (p[i] == '\n') {
1802  av_bprintf(&buf, "%i\t", ++line);
1803  av_bprint_append_data(&buf, start, &p[i] - start + 1);
1804  start = &p[i + 1];
1805  }
1806  }
1807 
1808  av_log(ctx, prio, "Shader %s: \n%s", shd->name, buf.str);
1809  av_bprint_finalize(&buf, NULL);
1810 }
1811 
1813 {
1814  VkResult ret;
1815  FFVulkanFunctions *vk = &s->vkfn;
1816  VkPipelineLayoutCreateInfo pipeline_layout_info;
1817 
1818  /* Finally create the pipeline layout */
1819  pipeline_layout_info = (VkPipelineLayoutCreateInfo) {
1820  .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
1821  .pSetLayouts = shd->desc_layout,
1822  .setLayoutCount = shd->nb_descriptor_sets,
1823  .pushConstantRangeCount = shd->push_consts_num,
1824  .pPushConstantRanges = shd->push_consts,
1825  };
1826 
1827  ret = vk->CreatePipelineLayout(s->hwctx->act_dev, &pipeline_layout_info,
1828  s->hwctx->alloc, &shd->pipeline_layout);
1829  if (ret != VK_SUCCESS) {
1830  av_log(s, AV_LOG_ERROR, "Unable to init pipeline layout: %s\n",
1831  ff_vk_ret2str(ret));
1832  return AVERROR_EXTERNAL;
1833  }
1834 
1835  return 0;
1836 }
1837 
1839  VkShaderModule *mod,
1840  uint8_t *spirv, size_t spirv_len)
1841 {
1842  VkResult ret;
1843  FFVulkanFunctions *vk = &s->vkfn;
1844 
1845  VkShaderModuleCreateInfo shader_module_info = {
1846  .sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO,
1847  .pNext = NULL,
1848  .flags = 0x0,
1849  .pCode = (void *)spirv,
1850  .codeSize = spirv_len,
1851  };
1852 
1853  ret = vk->CreateShaderModule(s->hwctx->act_dev, &shader_module_info,
1854  s->hwctx->alloc, mod);
1855  if (ret != VK_SUCCESS) {
1856  av_log(s, AV_LOG_VERBOSE, "Error creating shader module: %s\n",
1857  ff_vk_ret2str(ret));
1858  return AVERROR_EXTERNAL;
1859  }
1860 
1861  return 0;
1862 }
1863 
1865  VkShaderModule mod, const char *entrypoint)
1866 {
1867  VkResult ret;
1868  FFVulkanFunctions *vk = &s->vkfn;
1869 
1870  VkComputePipelineCreateInfo pipeline_create_info = {
1871  .sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,
1872  .flags = (s->extensions & FF_VK_EXT_DESCRIPTOR_BUFFER) ?
1873  VK_PIPELINE_CREATE_DESCRIPTOR_BUFFER_BIT_EXT : 0x0,
1874  .layout = shd->pipeline_layout,
1875  .stage = (VkPipelineShaderStageCreateInfo) {
1876  .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
1877  .pNext = shd->subgroup_info.requiredSubgroupSize ?
1878  &shd->subgroup_info : NULL,
1879  .pName = entrypoint,
1880  .flags = shd->subgroup_info.requiredSubgroupSize ?
1881  VK_PIPELINE_SHADER_STAGE_CREATE_REQUIRE_FULL_SUBGROUPS_BIT : 0x0,
1882  .stage = shd->stage,
1883  .module = mod,
1884  },
1885  };
1886 
1887  ret = vk->CreateComputePipelines(s->hwctx->act_dev, VK_NULL_HANDLE, 1,
1888  &pipeline_create_info,
1889  s->hwctx->alloc, &shd->pipeline);
1890  if (ret != VK_SUCCESS) {
1891  av_log(s, AV_LOG_ERROR, "Unable to init compute pipeline: %s\n",
1892  ff_vk_ret2str(ret));
1893  return AVERROR_EXTERNAL;
1894  }
1895 
1896  return 0;
1897 }
1898 
1900  uint8_t *spirv, size_t spirv_len,
1901  const char *entrypoint)
1902 {
1903  VkResult ret;
1904  FFVulkanFunctions *vk = &s->vkfn;
1905  size_t shader_size = 0;
1906 
1907  VkShaderCreateInfoEXT shader_obj_create = {
1908  .sType = VK_STRUCTURE_TYPE_SHADER_CREATE_INFO_EXT,
1909  .flags = shd->subgroup_info.requiredSubgroupSize ?
1910  VK_SHADER_CREATE_REQUIRE_FULL_SUBGROUPS_BIT_EXT : 0x0,
1911  .stage = shd->stage,
1912  .nextStage = 0,
1913  .codeType = VK_SHADER_CODE_TYPE_SPIRV_EXT,
1914  .pCode = spirv,
1915  .codeSize = spirv_len,
1916  .pName = entrypoint,
1917  .pSetLayouts = shd->desc_layout,
1918  .setLayoutCount = shd->nb_descriptor_sets,
1919  .pushConstantRangeCount = shd->push_consts_num,
1920  .pPushConstantRanges = shd->push_consts,
1921  .pSpecializationInfo = NULL,
1922  };
1923 
1924  ret = vk->CreateShadersEXT(s->hwctx->act_dev, 1, &shader_obj_create,
1925  s->hwctx->alloc, &shd->object);
1926  if (ret != VK_SUCCESS) {
1927  av_log(s, AV_LOG_ERROR, "Unable to create shader object: %s\n",
1928  ff_vk_ret2str(ret));
1929  return AVERROR_EXTERNAL;
1930  }
1931 
1932  if (vk->GetShaderBinaryDataEXT(s->hwctx->act_dev, shd->object,
1933  &shader_size, NULL) == VK_SUCCESS)
1934  av_log(s, AV_LOG_VERBOSE, "Shader %s size: %zu binary (%zu SPIR-V)\n",
1935  shd->name, shader_size, spirv_len);
1936 
1937  return 0;
1938 }
1939 
1941 {
1942  VkResult ret;
1943  FFVulkanFunctions *vk = &s->vkfn;
1944 
1946  sizeof(*shd->desc_layout));
1947  if (!shd->desc_layout)
1948  return AVERROR(ENOMEM);
1949 
1950  if (!(s->extensions & FF_VK_EXT_DESCRIPTOR_BUFFER)) {
1951  int has_singular = 0;
1952  for (int i = 0; i < shd->nb_descriptor_sets; i++) {
1953  if (shd->desc_set[i].singular) {
1954  has_singular = 1;
1955  break;
1956  }
1957  }
1958  shd->use_push = (s->extensions & FF_VK_EXT_PUSH_DESCRIPTOR) &&
1959  (shd->nb_descriptor_sets == 1) &&
1960  !has_singular;
1961  }
1962 
1963  for (int i = 0; i < shd->nb_descriptor_sets; i++) {
1964  FFVulkanDescriptorSet *set = &shd->desc_set[i];
1965  VkDescriptorSetLayoutCreateInfo desc_layout_create = {
1966  .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
1967  .bindingCount = set->nb_bindings,
1968  .pBindings = set->binding,
1969  .flags = (s->extensions & FF_VK_EXT_DESCRIPTOR_BUFFER) ?
1970  VK_DESCRIPTOR_SET_LAYOUT_CREATE_DESCRIPTOR_BUFFER_BIT_EXT :
1971  (shd->use_push) ?
1972  VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR :
1973  0x0,
1974  };
1975 
1976  ret = vk->CreateDescriptorSetLayout(s->hwctx->act_dev,
1977  &desc_layout_create,
1978  s->hwctx->alloc,
1979  &shd->desc_layout[i]);
1980  if (ret != VK_SUCCESS) {
1981  av_log(s, AV_LOG_ERROR, "Unable to create descriptor set layout: %s",
1982  ff_vk_ret2str(ret));
1983  return AVERROR_EXTERNAL;
1984  }
1985 
1986  if (s->extensions & FF_VK_EXT_DESCRIPTOR_BUFFER) {
1987  vk->GetDescriptorSetLayoutSizeEXT(s->hwctx->act_dev, shd->desc_layout[i],
1988  &set->layout_size);
1989 
1990  set->aligned_size = FFALIGN(set->layout_size,
1991  s->desc_buf_props.descriptorBufferOffsetAlignment);
1992 
1993  for (int j = 0; j < set->nb_bindings; j++)
1994  vk->GetDescriptorSetLayoutBindingOffsetEXT(s->hwctx->act_dev,
1995  shd->desc_layout[i],
1996  j,
1997  &set->binding_offset[j]);
1998  }
1999  }
2000 
2001  return 0;
2002 }
2003 
2005  uint8_t *spirv, size_t spirv_len,
2006  const char *entrypoint)
2007 {
2008  int err;
2009  FFVulkanFunctions *vk = &s->vkfn;
2010 
2011  err = init_descriptors(s, shd);
2012  if (err < 0)
2013  return err;
2014 
2015  err = init_pipeline_layout(s, shd);
2016  if (err < 0)
2017  return err;
2018 
2019  if (s->extensions & FF_VK_EXT_DESCRIPTOR_BUFFER) {
2021  sizeof(*shd->bound_buffer_indices));
2022  if (!shd->bound_buffer_indices)
2023  return AVERROR(ENOMEM);
2024 
2025  for (int i = 0; i < shd->nb_descriptor_sets; i++)
2026  shd->bound_buffer_indices[i] = i;
2027  }
2028 
2029  if (s->extensions & FF_VK_EXT_SHADER_OBJECT) {
2030  err = create_shader_object(s, shd, spirv, spirv_len, entrypoint);
2031  if (err < 0)
2032  return err;
2033  } else {
2034  VkShaderModule mod;
2035  err = create_shader_module(s, shd, &mod, spirv, spirv_len);
2036  if (err < 0)
2037  return err;
2038 
2039  switch (shd->bind_point) {
2040  case VK_PIPELINE_BIND_POINT_COMPUTE:
2041  err = init_compute_pipeline(s, shd, mod, entrypoint);
2042  break;
2043  default:
2044  av_log(s, AV_LOG_ERROR, "Unsupported shader type: %i\n",
2045  shd->bind_point);
2046  err = AVERROR(EINVAL);
2047  break;
2048  };
2049 
2050  vk->DestroyShaderModule(s->hwctx->act_dev, mod, s->hwctx->alloc);
2051  if (err < 0)
2052  return err;
2053  }
2054 
2055  return 0;
2056 }
2057 
2058 static const struct descriptor_props {
2059  size_t struct_size; /* Size of the opaque which updates the descriptor */
2060  const char *type;
2062  int mem_quali; /* Can use a memory qualifier */
2063  int dim_needed; /* Must indicate dimension */
2064  int buf_content; /* Must indicate buffer contents */
2065 } descriptor_props[] = {
2066  [VK_DESCRIPTOR_TYPE_SAMPLER] = { sizeof(VkDescriptorImageInfo), "sampler", 1, 0, 0, 0, },
2067  [VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE] = { sizeof(VkDescriptorImageInfo), "texture", 1, 0, 1, 0, },
2068  [VK_DESCRIPTOR_TYPE_STORAGE_IMAGE] = { sizeof(VkDescriptorImageInfo), "image", 1, 1, 1, 0, },
2069  [VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT] = { sizeof(VkDescriptorImageInfo), "subpassInput", 1, 0, 0, 0, },
2070  [VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER] = { sizeof(VkDescriptorImageInfo), "sampler", 1, 0, 1, 0, },
2071  [VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER] = { sizeof(VkDescriptorBufferInfo), NULL, 1, 0, 0, 1, },
2072  [VK_DESCRIPTOR_TYPE_STORAGE_BUFFER] = { sizeof(VkDescriptorBufferInfo), "buffer", 0, 1, 0, 1, },
2073  [VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC] = { sizeof(VkDescriptorBufferInfo), NULL, 1, 0, 0, 1, },
2074  [VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC] = { sizeof(VkDescriptorBufferInfo), "buffer", 0, 1, 0, 1, },
2075  [VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER] = { sizeof(VkBufferView), "samplerBuffer", 1, 0, 0, 0, },
2076  [VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER] = { sizeof(VkBufferView), "imageBuffer", 1, 0, 0, 0, },
2077 };
2078 
2081  int singular, int print_to_shader_only)
2082 {
2083  int has_sampler = 0;
2085 
2086  if (print_to_shader_only)
2087  goto print;
2088 
2089  /* Actual layout allocated for the pipeline */
2090  set = av_realloc_array(shd->desc_set,
2091  sizeof(*shd->desc_set),
2092  shd->nb_descriptor_sets + 1);
2093  if (!set)
2094  return AVERROR(ENOMEM);
2095  shd->desc_set = set;
2096 
2097  set = &set[shd->nb_descriptor_sets];
2098  memset(set, 0, sizeof(*set));
2099 
2100  set->binding = av_calloc(nb, sizeof(*set->binding));
2101  if (!set->binding)
2102  return AVERROR(ENOMEM);
2103 
2104  set->binding_offset = av_calloc(nb, sizeof(*set->binding_offset));
2105  if (!set->binding_offset) {
2106  av_freep(&set->binding);
2107  return AVERROR(ENOMEM);
2108  }
2109 
2110  for (int i = 0; i < nb; i++) {
2111  set->binding[i].binding = i;
2112  set->binding[i].descriptorType = desc[i].type;
2113  set->binding[i].descriptorCount = FFMAX(desc[i].elems, 1);
2114  set->binding[i].stageFlags = desc[i].stages;
2115  set->binding[i].pImmutableSamplers = desc[i].samplers;
2116 
2117  if (desc[i].type == VK_DESCRIPTOR_TYPE_SAMPLER ||
2118  desc[i].type == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
2119  has_sampler |= 1;
2120  }
2121 
2122  set->usage = VK_BUFFER_USAGE_RESOURCE_DESCRIPTOR_BUFFER_BIT_EXT |
2123  VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT;
2124  if (has_sampler)
2125  set->usage |= VK_BUFFER_USAGE_SAMPLER_DESCRIPTOR_BUFFER_BIT_EXT;
2126 
2127  if (!(s->extensions & FF_VK_EXT_DESCRIPTOR_BUFFER)) {
2128  for (int i = 0; i < nb; i++) {
2129  int j;
2130  VkDescriptorPoolSize *desc_pool_size;
2131  for (j = 0; j < shd->nb_desc_pool_size; j++)
2132  if (shd->desc_pool_size[j].type == desc[i].type)
2133  break;
2134  if (j >= shd->nb_desc_pool_size) {
2135  desc_pool_size = av_realloc_array(shd->desc_pool_size,
2136  sizeof(*desc_pool_size),
2137  shd->nb_desc_pool_size + 1);
2138  if (!desc_pool_size)
2139  return AVERROR(ENOMEM);
2140 
2141  shd->desc_pool_size = desc_pool_size;
2142  shd->nb_desc_pool_size++;
2143  memset(&desc_pool_size[j], 0, sizeof(VkDescriptorPoolSize));
2144  }
2145  shd->desc_pool_size[j].type = desc[i].type;
2146  shd->desc_pool_size[j].descriptorCount += FFMAX(desc[i].elems, 1);
2147  }
2148  }
2149 
2150  set->singular = singular;
2151  set->nb_bindings = nb;
2152  shd->nb_descriptor_sets++;
2153 
2154 print:
2155  /* Write shader info */
2156  for (int i = 0; i < nb; i++) {
2157  const struct descriptor_props *prop = &descriptor_props[desc[i].type];
2158  GLSLA("layout (set = %i, binding = %i", FFMAX(shd->nb_descriptor_sets - 1, 0), i);
2159 
2160  if (desc[i].mem_layout)
2161  GLSLA(", %s", desc[i].mem_layout);
2162  GLSLA(")");
2163 
2164  if (prop->is_uniform)
2165  GLSLA(" uniform");
2166 
2167  if (prop->mem_quali && desc[i].mem_quali)
2168  GLSLA(" %s", desc[i].mem_quali);
2169 
2170  if (prop->type) {
2171  GLSLA(" ");
2172  if (desc[i].type == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE) {
2173  if (desc[i].mem_layout) {
2174  int len = strlen(desc[i].mem_layout);
2175  if (desc[i].mem_layout[len - 1] == 'i' &&
2176  desc[i].mem_layout[len - 2] == 'u') {
2177  GLSLA("u");
2178  } else if (desc[i].mem_layout[len - 1] == 'i') {
2179  GLSLA("i");
2180  }
2181  }
2182  }
2183  GLSLA("%s", prop->type);
2184  }
2185 
2186  if (prop->dim_needed)
2187  GLSLA("%iD", desc[i].dimensions);
2188 
2189  GLSLA(" %s", desc[i].name);
2190 
2191  if (prop->buf_content) {
2192  GLSLA(" {\n ");
2193  if (desc[i].elems) {
2194  GLSLA("%s", desc[i].buf_content);
2195  GLSLA("[%i];", desc[i].elems);
2196  } else {
2197  GLSLA("%s", desc[i].buf_content);
2198  }
2199  GLSLA("\n}");
2200  } else if (desc[i].elems > 0) {
2201  GLSLA("[%i]", desc[i].elems);
2202  }
2203 
2204  GLSLA(";");
2205  GLSLA("\n");
2206  }
2207  GLSLA("\n");
2208 
2209  return 0;
2210 }
2211 
2213  FFVulkanShader *shd)
2214 {
2215  int err;
2216  FFVulkanShaderData *sd;
2217 
2218  if (!shd->nb_descriptor_sets)
2219  return 0;
2220 
2221  sd = av_realloc_array(pool->reg_shd,
2222  sizeof(*pool->reg_shd),
2223  pool->nb_reg_shd + 1);
2224  if (!sd)
2225  return AVERROR(ENOMEM);
2226 
2227  pool->reg_shd = sd;
2228  sd = &sd[pool->nb_reg_shd++];
2229  memset(sd, 0, sizeof(*sd));
2230 
2231  sd->shd = shd;
2233 
2234  if (s->extensions & FF_VK_EXT_DESCRIPTOR_BUFFER) {
2235  sd->desc_bind = av_malloc_array(sd->nb_descriptor_sets, sizeof(*sd->desc_bind));
2236  if (!sd->desc_bind)
2237  return AVERROR(ENOMEM);
2238 
2239  sd->desc_set_buf = av_calloc(sd->nb_descriptor_sets, sizeof(*sd->desc_set_buf));
2240  if (!sd->desc_set_buf)
2241  return AVERROR(ENOMEM);
2242 
2243  for (int i = 0; i < sd->nb_descriptor_sets; i++) {
2244  FFVulkanDescriptorSet *set = &shd->desc_set[i];
2246  int nb = set->singular ? 1 : pool->pool_size;
2247 
2248  err = ff_vk_create_buf(s, &sdb->buf,
2249  set->aligned_size*nb,
2250  NULL, NULL, set->usage,
2251  VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT |
2252  VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
2253  VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
2254  if (err < 0)
2255  return err;
2256 
2257  err = ff_vk_map_buffer(s, &sdb->buf, &sdb->desc_mem, 0);
2258  if (err < 0)
2259  return err;
2260 
2261  sd->desc_bind[i] = (VkDescriptorBufferBindingInfoEXT) {
2262  .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_BUFFER_BINDING_INFO_EXT,
2263  .usage = set->usage,
2264  .address = sdb->buf.address,
2265  };
2266  }
2267  } else if (!shd->use_push) {
2268  VkResult ret;
2269  FFVulkanFunctions *vk = &s->vkfn;
2270  VkDescriptorSetLayout *tmp_layouts;
2271  VkDescriptorSetAllocateInfo set_alloc_info;
2272  VkDescriptorPoolCreateInfo pool_create_info;
2273 
2274  for (int i = 0; i < shd->nb_desc_pool_size; i++)
2275  shd->desc_pool_size[i].descriptorCount *= pool->pool_size;
2276 
2277  pool_create_info = (VkDescriptorPoolCreateInfo) {
2278  .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
2279  .flags = 0,
2280  .pPoolSizes = shd->desc_pool_size,
2281  .poolSizeCount = shd->nb_desc_pool_size,
2282  .maxSets = sd->nb_descriptor_sets*pool->pool_size,
2283  };
2284 
2285  ret = vk->CreateDescriptorPool(s->hwctx->act_dev, &pool_create_info,
2286  s->hwctx->alloc, &sd->desc_pool);
2287  if (ret != VK_SUCCESS) {
2288  av_log(s, AV_LOG_ERROR, "Unable to create descriptor pool: %s\n",
2289  ff_vk_ret2str(ret));
2290  return AVERROR_EXTERNAL;
2291  }
2292 
2293  tmp_layouts = av_malloc_array(pool_create_info.maxSets, sizeof(*tmp_layouts));
2294  if (!tmp_layouts)
2295  return AVERROR(ENOMEM);
2296 
2297  /* Colate each execution context's descriptor set layouts */
2298  for (int i = 0; i < pool->pool_size; i++)
2299  for (int j = 0; j < sd->nb_descriptor_sets; j++)
2300  tmp_layouts[i*sd->nb_descriptor_sets + j] = shd->desc_layout[j];
2301 
2302  set_alloc_info = (VkDescriptorSetAllocateInfo) {
2303  .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
2304  .descriptorPool = sd->desc_pool,
2305  .pSetLayouts = tmp_layouts,
2306  .descriptorSetCount = pool_create_info.maxSets,
2307  };
2308 
2309  sd->desc_sets = av_malloc_array(pool_create_info.maxSets,
2310  sizeof(*tmp_layouts));
2311  if (!sd->desc_sets) {
2312  av_free(tmp_layouts);
2313  return AVERROR(ENOMEM);
2314  }
2315  ret = vk->AllocateDescriptorSets(s->hwctx->act_dev, &set_alloc_info,
2316  sd->desc_sets);
2317  av_free(tmp_layouts);
2318  if (ret != VK_SUCCESS) {
2319  av_log(s, AV_LOG_ERROR, "Unable to allocate descriptor set: %s\n",
2320  ff_vk_ret2str(ret));
2321  av_freep(&sd->desc_sets);
2322  return AVERROR_EXTERNAL;
2323  }
2324  }
2325 
2326  return 0;
2327 }
2328 
2330  FFVulkanShader *shd)
2331 {
2332  for (int i = 0; i < e->parent->nb_reg_shd; i++)
2333  if (e->parent->reg_shd[i].shd == shd)
2334  return &e->parent->reg_shd[i];
2335  return NULL;
2336 }
2337 
2339  FFVulkanShader *shd, int set,
2340  int bind_idx, int array_idx,
2341  VkDescriptorGetInfoEXT *desc_get_info,
2342  size_t desc_size)
2343 {
2344  FFVulkanFunctions *vk = &s->vkfn;
2345  FFVulkanDescriptorSet *desc_set = &shd->desc_set[set];
2346  FFVulkanShaderData *sd = get_shd_data(e, shd);
2347  const size_t exec_offset = desc_set->singular ? 0 : desc_set->aligned_size*e->idx;
2348 
2349  void *desc = sd->desc_set_buf[set].desc_mem + /* Base */
2350  exec_offset + /* Execution context */
2351  desc_set->binding_offset[bind_idx] + /* Descriptor binding */
2352  array_idx*desc_size; /* Array position */
2353 
2354  vk->GetDescriptorEXT(s->hwctx->act_dev, desc_get_info, desc_size, desc);
2355 }
2356 
2358  FFVulkanShader *shd, int set,
2359  VkWriteDescriptorSet *write_info)
2360 {
2361  FFVulkanFunctions *vk = &s->vkfn;
2362  FFVulkanDescriptorSet *desc_set = &shd->desc_set[set];
2363  FFVulkanShaderData *sd = get_shd_data(e, shd);
2364 
2365  if (desc_set->singular) {
2366  for (int i = 0; i < e->parent->pool_size; i++) {
2367  write_info->dstSet = sd->desc_sets[i*sd->nb_descriptor_sets + set];
2368  vk->UpdateDescriptorSets(s->hwctx->act_dev, 1, write_info, 0, NULL);
2369  }
2370  } else {
2371  if (shd->use_push) {
2372  vk->CmdPushDescriptorSetKHR(e->buf,
2373  shd->bind_point,
2374  shd->pipeline_layout,
2375  set, 1,
2376  write_info);
2377  } else {
2378  write_info->dstSet = sd->desc_sets[e->idx*sd->nb_descriptor_sets + set];
2379  vk->UpdateDescriptorSets(s->hwctx->act_dev, 1, write_info, 0, NULL);
2380  }
2381  }
2382 }
2383 
2385  FFVkExecContext *e, int set, int bind, int offs,
2386  VkImageView view, VkImageLayout layout,
2387  VkSampler sampler)
2388 {
2389  FFVulkanDescriptorSet *desc_set = &shd->desc_set[set];
2390 
2391  if (s->extensions & FF_VK_EXT_DESCRIPTOR_BUFFER) {
2392  VkDescriptorGetInfoEXT desc_get_info = {
2393  .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_GET_INFO_EXT,
2394  .type = desc_set->binding[bind].descriptorType,
2395  };
2396  VkDescriptorImageInfo desc_img_info = {
2397  .imageView = view,
2398  .sampler = sampler,
2399  .imageLayout = layout,
2400  };
2401  size_t desc_size;
2402 
2403  switch (desc_get_info.type) {
2404  case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
2405  desc_get_info.data.pSampledImage = &desc_img_info;
2406  desc_size = s->desc_buf_props.sampledImageDescriptorSize;
2407  break;
2408  case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
2409  desc_get_info.data.pStorageImage = &desc_img_info;
2410  desc_size = s->desc_buf_props.storageImageDescriptorSize;
2411  break;
2412  case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
2413  desc_get_info.data.pInputAttachmentImage = &desc_img_info;
2414  desc_size = s->desc_buf_props.inputAttachmentDescriptorSize;
2415  break;
2416  case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
2417  desc_get_info.data.pCombinedImageSampler = &desc_img_info;
2418  desc_size = s->desc_buf_props.combinedImageSamplerDescriptorSize;
2419  break;
2420  default:
2421  av_log(s, AV_LOG_ERROR, "Invalid descriptor type at set %i binding %i: %i!\n",
2422  set, bind, desc_get_info.type);
2423  return AVERROR(EINVAL);
2424  break;
2425  };
2426 
2427  update_set_descriptor(s, e, shd, set, bind, offs,
2428  &desc_get_info, desc_size);
2429  } else {
2430  VkDescriptorImageInfo desc_pool_write_info_img = {
2431  .sampler = sampler,
2432  .imageView = view,
2433  .imageLayout = layout,
2434  };
2435  VkWriteDescriptorSet desc_pool_write_info = {
2436  .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
2437  .dstBinding = bind,
2438  .descriptorCount = 1,
2439  .dstArrayElement = offs,
2440  .descriptorType = desc_set->binding[bind].descriptorType,
2441  .pImageInfo = &desc_pool_write_info_img,
2442  };
2443  update_set_pool_write(s, e, shd, set, &desc_pool_write_info);
2444  }
2445 
2446  return 0;
2447 }
2448 
2450  FFVulkanShader *shd,
2451  int set, int bind, int elem,
2452  FFVkBuffer *buf, VkDeviceSize offset, VkDeviceSize len,
2453  VkFormat fmt)
2454 {
2455  FFVulkanDescriptorSet *desc_set = &shd->desc_set[set];
2456 
2457  if (s->extensions & FF_VK_EXT_DESCRIPTOR_BUFFER) {
2458  VkDescriptorGetInfoEXT desc_get_info = {
2459  .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_GET_INFO_EXT,
2460  .type = desc_set->binding[bind].descriptorType,
2461  };
2462  VkDescriptorAddressInfoEXT desc_buf_info = {
2463  .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_ADDRESS_INFO_EXT,
2464  .address = buf->address + offset,
2465  .range = len,
2466  .format = fmt,
2467  };
2468  size_t desc_size;
2469 
2470  switch (desc_get_info.type) {
2471  case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
2472  desc_get_info.data.pUniformBuffer = &desc_buf_info;
2473  desc_size = s->desc_buf_props.uniformBufferDescriptorSize;
2474  break;
2475  case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
2476  desc_get_info.data.pStorageBuffer = &desc_buf_info;
2477  desc_size = s->desc_buf_props.storageBufferDescriptorSize;
2478  break;
2479  case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
2480  desc_get_info.data.pUniformTexelBuffer = &desc_buf_info;
2481  desc_size = s->desc_buf_props.uniformTexelBufferDescriptorSize;
2482  break;
2483  case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
2484  desc_get_info.data.pStorageTexelBuffer = &desc_buf_info;
2485  desc_size = s->desc_buf_props.storageTexelBufferDescriptorSize;
2486  break;
2487  default:
2488  av_log(s, AV_LOG_ERROR, "Invalid descriptor type at set %i binding %i: %i!\n",
2489  set, bind, desc_get_info.type);
2490  return AVERROR(EINVAL);
2491  break;
2492  };
2493 
2494  update_set_descriptor(s, e, shd, set, bind, elem, &desc_get_info, desc_size);
2495  } else {
2496  VkDescriptorBufferInfo desc_pool_write_info_buf = {
2497  .buffer = buf->buf,
2498  .offset = offset,
2499  .range = len,
2500  };
2501  VkWriteDescriptorSet desc_pool_write_info = {
2502  .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
2503  .dstBinding = bind,
2504  .descriptorCount = 1,
2505  .dstArrayElement = elem,
2506  .descriptorType = desc_set->binding[bind].descriptorType,
2507  .pBufferInfo = &desc_pool_write_info_buf,
2508  };
2509  update_set_pool_write(s, e, shd, set, &desc_pool_write_info);
2510  }
2511 
2512  return 0;
2513 }
2514 
2516  FFVulkanShader *shd, AVFrame *f,
2517  VkImageView *views, int set, int binding,
2518  VkImageLayout layout, VkSampler sampler)
2519 {
2520  AVHWFramesContext *hwfc = (AVHWFramesContext *)f->hw_frames_ctx->data;
2521  const int nb_planes = av_pix_fmt_count_planes(hwfc->sw_format);
2522 
2523  for (int i = 0; i < nb_planes; i++)
2524  vk_set_descriptor_image(s, shd, e, set, binding, i,
2525  views[i], layout, sampler);
2526 }
2527 
2529  FFVulkanShader *shd,
2530  VkShaderStageFlagBits stage,
2531  int offset, size_t size, void *src)
2532 {
2533  FFVulkanFunctions *vk = &s->vkfn;
2534  vk->CmdPushConstants(e->buf, shd->pipeline_layout,
2535  stage, offset, size, src);
2536 }
2537 
2539  FFVulkanShader *shd)
2540 {
2541  FFVulkanFunctions *vk = &s->vkfn;
2542  VkDeviceSize offsets[1024];
2543  FFVulkanShaderData *sd = get_shd_data(e, shd);
2544 
2545  if (s->extensions & FF_VK_EXT_SHADER_OBJECT) {
2546  VkShaderStageFlagBits stages = shd->stage;
2547  vk->CmdBindShadersEXT(e->buf, 1, &stages, &shd->object);
2548  } else {
2549  vk->CmdBindPipeline(e->buf, shd->bind_point, shd->pipeline);
2550  }
2551 
2552  if (sd && sd->nb_descriptor_sets) {
2553  if (s->extensions & FF_VK_EXT_DESCRIPTOR_BUFFER) {
2554  for (int i = 0; i < sd->nb_descriptor_sets; i++)
2555  offsets[i] = shd->desc_set[i].singular ? 0 : shd->desc_set[i].aligned_size*e->idx;
2556 
2557  /* Bind descriptor buffers */
2558  vk->CmdBindDescriptorBuffersEXT(e->buf, sd->nb_descriptor_sets, sd->desc_bind);
2559  /* Binding offsets */
2560  vk->CmdSetDescriptorBufferOffsetsEXT(e->buf, shd->bind_point, shd->pipeline_layout,
2561  0, sd->nb_descriptor_sets,
2563  } else if (!shd->use_push) {
2564  vk->CmdBindDescriptorSets(e->buf, shd->bind_point, shd->pipeline_layout,
2565  0, sd->nb_descriptor_sets,
2566  &sd->desc_sets[e->idx*sd->nb_descriptor_sets],
2567  0, NULL);
2568  }
2569  }
2570 }
2571 
2573 {
2574  FFVulkanFunctions *vk = &s->vkfn;
2575 
2576  av_bprint_finalize(&shd->src, NULL);
2577 
2578 #if 0
2579  if (shd->shader.module)
2580  vk->DestroyShaderModule(s->hwctx->act_dev, shd->shader.module,
2581  s->hwctx->alloc);
2582 #endif
2583 
2584  if (shd->object)
2585  vk->DestroyShaderEXT(s->hwctx->act_dev, shd->object, s->hwctx->alloc);
2586  if (shd->pipeline)
2587  vk->DestroyPipeline(s->hwctx->act_dev, shd->pipeline, s->hwctx->alloc);
2588  if (shd->pipeline_layout)
2589  vk->DestroyPipelineLayout(s->hwctx->act_dev, shd->pipeline_layout,
2590  s->hwctx->alloc);
2591 
2592  for (int i = 0; i < shd->nb_descriptor_sets; i++) {
2593  FFVulkanDescriptorSet *set = &shd->desc_set[i];
2594  av_free(set->binding);
2595  av_free(set->binding_offset);
2596  }
2597 
2598  for (int i = 0; i < shd->nb_descriptor_sets; i++)
2599  if (shd->desc_layout[i])
2600  vk->DestroyDescriptorSetLayout(s->hwctx->act_dev, shd->desc_layout[i],
2601  s->hwctx->alloc);
2602 
2603  av_freep(&shd->desc_pool_size);
2604  av_freep(&shd->desc_layout);
2605  av_freep(&shd->desc_set);
2607  av_freep(&shd->push_consts);
2608  shd->push_consts_num = 0;
2609 }
2610 
2612 {
2613  av_freep(&s->query_props);
2614  av_freep(&s->qf_props);
2615  av_freep(&s->video_props);
2616  av_freep(&s->coop_mat_props);
2617 
2618  av_buffer_unref(&s->device_ref);
2619  av_buffer_unref(&s->frames_ref);
2620 }
2621 
2622 int ff_vk_init(FFVulkanContext *s, void *log_parent,
2623  AVBufferRef *device_ref, AVBufferRef *frames_ref)
2624 {
2625  int err;
2626 
2627  static const AVClass vulkan_context_class = {
2628  .class_name = "vk",
2629  .version = LIBAVUTIL_VERSION_INT,
2630  .parent_log_context_offset = offsetof(FFVulkanContext, log_parent),
2631  };
2632 
2633  memset(s, 0, sizeof(*s));
2634  s->log_parent = log_parent;
2635  s->class = &vulkan_context_class;
2636 
2637  if (frames_ref) {
2638  s->frames_ref = av_buffer_ref(frames_ref);
2639  if (!s->frames_ref)
2640  return AVERROR(ENOMEM);
2641 
2642  s->frames = (AVHWFramesContext *)s->frames_ref->data;
2643  s->hwfc = s->frames->hwctx;
2644 
2645  device_ref = s->frames->device_ref;
2646  }
2647 
2648  s->device_ref = av_buffer_ref(device_ref);
2649  if (!s->device_ref) {
2650  ff_vk_uninit(s);
2651  return AVERROR(ENOMEM);
2652  }
2653 
2654  s->device = (AVHWDeviceContext *)s->device_ref->data;
2655  s->hwctx = s->device->hwctx;
2656 
2657  s->extensions = ff_vk_extensions_to_mask(s->hwctx->enabled_dev_extensions,
2658  s->hwctx->nb_enabled_dev_extensions);
2659  s->extensions |= ff_vk_extensions_to_mask(s->hwctx->enabled_inst_extensions,
2660  s->hwctx->nb_enabled_inst_extensions);
2661 
2662  err = ff_vk_load_functions(s->device, &s->vkfn, s->extensions, 1, 1);
2663  if (err < 0) {
2664  ff_vk_uninit(s);
2665  return err;
2666  }
2667 
2668  err = ff_vk_load_props(s);
2669  if (err < 0) {
2670  ff_vk_uninit(s);
2671  return err;
2672  }
2673 
2674  return 0;
2675 }
FFVulkanShader::bind_point
VkPipelineBindPoint bind_point
Definition: vulkan.h:194
vulkan_loader.h
AV_PIX_FMT_GBRAP16
#define AV_PIX_FMT_GBRAP16
Definition: pixfmt.h:533
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:1486
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:132
ff_vk_shader_free
void ff_vk_shader_free(FFVulkanContext *s, FFVulkanShader *shd)
Free a shader.
Definition: vulkan.c:2572
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:1715
av_bprint_init
void av_bprint_init(AVBPrint *buf, unsigned size_init, unsigned size_max)
Definition: bprint.c:69
AVBufferPool
The buffer pool.
Definition: buffer_internal.h:88
atomic_fetch_add
#define atomic_fetch_add(object, operand)
Definition: stdatomic.h:137
FFVkExecPool::contexts
FFVkExecContext * contexts
Definition: vulkan.h:245
FFVkExecPool::idx
atomic_uint_least64_t idx
Definition: vulkan.h:246
FFVulkanDescriptorSetData
Definition: vulkan.h:224
FFVulkanShader::nb_desc_pool_size
int nb_desc_pool_size
Definition: vulkan.h:221
ff_vk_exec_pool_init
int ff_vk_exec_pool_init(FFVulkanContext *s, AVVulkanDeviceQueueFamily *qf, FFVkExecPool *pool, int nb_contexts, int nb_queries, VkQueryType query_type, int query_64bit, const void *query_create_pnext)
Allocates/frees an execution pool.
Definition: vulkan.c:296
FFVulkanShaderData
Definition: vulkan.h:230
DEBUG
#define DEBUG
Definition: vf_framerate.c:29
ARR_REALLOC
#define ARR_REALLOC(str, arr, alloc_s, cnt)
Definition: vulkan.c:598
FFVkExecContext::qf
int qf
Definition: vulkan.h:110
FFVulkanDescriptorSet::aligned_size
VkDeviceSize aligned_size
Definition: vulkan.h:171
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:449
FFVulkanShaderData::shd
FFVulkanShader * shd
Definition: vulkan.h:232
descriptor_props::is_uniform
int is_uniform
Definition: vulkan.c:2061
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:766
av_frame_free
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
Definition: frame.c:163
AVFrame
This structure describes decoded (raw) audio or video data.
Definition: frame.h:410
ff_vk_map_buffer
static int ff_vk_map_buffer(FFVulkanContext *s, FFVkBuffer *buf, uint8_t **mem, int invalidate)
Definition: vulkan.h:495
FFVulkanShader::subgroup_info
VkPipelineShaderStageRequiredSubgroupSizeCreateInfo subgroup_info
Definition: vulkan.h:197
AV_PIX_FMT_Y216
#define AV_PIX_FMT_Y216
Definition: pixfmt.h:569
ff_vk_find_struct
static const void * ff_vk_find_struct(const void *chain, VkStructureType stype)
Definition: vulkan.h:321
FFVulkanShader::pipeline
VkPipeline pipeline
Definition: vulkan.h:201
FFVkExecContext::sem_sig_alloc
unsigned int sem_sig_alloc
Definition: vulkan.h:145
FFVulkanShaderData::desc_bind
VkDescriptorBufferBindingInfoEXT * desc_bind
Definition: vulkan.h:237
FFVulkanShader::src
AVBPrint src
Definition: vulkan.h:187
alloc_data_buf
static AVBufferRef * alloc_data_buf(void *opaque, size_t size)
Definition: vulkan.c:1165
FFVulkanShader::use_push
int use_push
Definition: vulkan.h:219
data
const char data[16]
Definition: mxf.c:149
AV_PIX_FMT_RGBA128
#define AV_PIX_FMT_RGBA128
Definition: pixfmt.h:591
AV_PIX_FMT_YUV420P10
#define AV_PIX_FMT_YUV420P10
Definition: pixfmt.h:510
AV_PIX_FMT_XV30
#define AV_PIX_FMT_XV30
Definition: pixfmt.h:570
AV_LOG_VERBOSE
#define AV_LOG_VERBOSE
Detailed information.
Definition: log.h:225
TempSyncCtx::nb_sem
int nb_sem
Definition: vulkan.c:609
FFVkBuffer::address
VkDeviceAddress address
Definition: vulkan.h:92
FFVkExecContext::sem_wait
VkSemaphoreSubmitInfo * sem_wait
Definition: vulkan.h:140
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:2622
ff_vk_exec_get
FFVkExecContext * ff_vk_exec_get(FFVulkanContext *s, FFVkExecPool *pool)
Retrieve an execution pool.
Definition: vulkan.c:477
FF_VK_REP_NATIVE
@ FF_VK_REP_NATIVE
Definition: vulkan.h:374
ff_vk_uninit
void ff_vk_uninit(FFVulkanContext *s)
Frees main context.
Definition: vulkan.c:2611
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:44
av_popcount
#define av_popcount
Definition: common.h:154
FF_VK_REP_INT
@ FF_VK_REP_INT
Definition: vulkan.h:378
FFVkExecPool::query_pool
VkQueryPool query_pool
Definition: vulkan.h:252
FFVkExecPool::nb_reg_shd
int nb_reg_shd
Definition: vulkan.h:263
FFVulkanDescriptorSetData::desc_mem
uint8_t * desc_mem
Definition: vulkan.h:227
FFVkExecContext::nb_sw_frame_deps
int nb_sw_frame_deps
Definition: vulkan.h:138
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:696
FFVulkanShaderData::desc_sets
VkDescriptorSet * desc_sets
Definition: vulkan.h:240
descriptor_props::type
const char * type
Definition: vulkan.c:2060
AV_PIX_FMT_P212
#define AV_PIX_FMT_P212
Definition: pixfmt.h:579
FFVkShaderRepFormat
FFVkShaderRepFormat
Returns the format to use for images in shaders.
Definition: vulkan.h:372
AVFrame::data
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition: frame.h:431
FFVkBuffer::buf
VkBuffer buf
Definition: vulkan.h:88
av_malloc
#define av_malloc(s)
Definition: tableprint_vlc.h:30
ImageViewCtx
Definition: vulkan.c:1485
FFVkExecContext::frame_update_alloc_size
unsigned int frame_update_alloc_size
Definition: vulkan.h:165
av_pix_fmt_count_planes
int av_pix_fmt_count_planes(enum AVPixelFormat pix_fmt)
Definition: pixdesc.c:3284
FFVulkanShader::desc_layout
VkDescriptorSetLayout * desc_layout
Definition: vulkan.h:215
AV_PIX_FMT_GBRP14
#define AV_PIX_FMT_GBRP14
Definition: pixfmt.h:528
AVVkFrame::img
VkImage img[AV_NUM_DATA_POINTERS]
Vulkan images to which the memory is bound to.
Definition: hwcontext_vulkan.h:307
AV_PIX_FMT_GBRAP
@ AV_PIX_FMT_GBRAP
planar GBRA 4:4:4:4 32bpp
Definition: pixfmt.h:212
destroy_avvkbuf
static void destroy_avvkbuf(void *opaque, uint8_t *data)
Definition: vulkan.c:1020
fail
#define fail()
Definition: checkasm.h:193
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:625
AV_PIX_FMT_GBRP10
#define AV_PIX_FMT_GBRP10
Definition: pixfmt.h:526
ff_vk_unmap_buffers
int ff_vk_unmap_buffers(FFVulkanContext *s, FFVkBuffer **buf, int nb_buffers, int flush)
Definition: vulkan.c:1102
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:2515
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:256
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:2212
AV_PIX_FMT_XV48
#define AV_PIX_FMT_XV48
Definition: pixfmt.h:572
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:2079
AV_PIX_FMT_GRAY16
#define AV_PIX_FMT_GRAY16
Definition: pixfmt.h:494
create_shader_module
static int create_shader_module(FFVulkanContext *s, FFVulkanShader *shd, VkShaderModule *mod, uint8_t *spirv, size_t spirv_len)
Definition: vulkan.c:1838
ff_vk_aspect_flag
VkImageAspectFlags ff_vk_aspect_flag(AVFrame *f, int p)
Get the aspect flag for a plane from an image.
Definition: vulkan.c:1284
FFVkExecPool::query_statuses
int query_statuses
Definition: vulkan.h:255
descriptor_props::struct_size
size_t struct_size
Definition: vulkan.c:2059
AVHWDeviceContext
This struct aggregates all the (hardware/vendor-specific) "high-level" state, i.e.
Definition: hwcontext.h:60
AV_PIX_FMT_YUV444P10
#define AV_PIX_FMT_YUV444P10
Definition: pixfmt.h:513
FFVulkanDescriptorSet::binding
VkDescriptorSetLayoutBinding * binding
Definition: vulkan.h:174
init_descriptors
static int init_descriptors(FFVulkanContext *s, FFVulkanShader *shd)
Definition: vulkan.c:1940
init_pipeline_layout
static int init_pipeline_layout(FFVulkanContext *s, FFVulkanShader *shd)
Definition: vulkan.c:1812
AV_PIX_FMT_Y210
#define AV_PIX_FMT_Y210
Definition: pixfmt.h:567
avassert.h
AVVulkanDeviceQueueFamily::num
int num
Definition: hwcontext_vulkan.h:37
GLSLC
#define GLSLC(N, S)
Definition: vulkan.h:44
FFVulkanDescriptorSetData::buf
FFVkBuffer buf
Definition: vulkan.h:226
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:209
FF_ARRAY_ELEMS
#define FF_ARRAY_ELEMS(a)
Definition: sinewin_tablegen.c:29
FFVkExecContext::frame_deps
AVFrame ** frame_deps
Definition: vulkan.h:131
AV_PIX_FMT_YUV422P16
#define AV_PIX_FMT_YUV422P16
Definition: pixfmt.h:522
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:1028
FFVkExecContext::queue_family_dst
uint32_t * queue_family_dst
Definition: vulkan.h:161
AV_PIX_FMT_GBRAP10
#define AV_PIX_FMT_GBRAP10
Definition: pixfmt.h:530
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:207
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
AV_PIX_FMT_GBRAP14
#define AV_PIX_FMT_GBRAP14
Definition: pixfmt.h:532
AV_PIX_FMT_GBRAP12
#define AV_PIX_FMT_GBRAP12
Definition: pixfmt.h:531
AV_PIX_FMT_RGB96
#define AV_PIX_FMT_RGB96
Definition: pixfmt.h:590
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:785
AV_PIX_FMT_YUV444P16
#define AV_PIX_FMT_YUV444P16
Definition: pixfmt.h:523
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:117
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:2338
ff_vk_exec_wait
void ff_vk_exec_wait(FFVulkanContext *s, FFVkExecContext *e)
Definition: vulkan.c:482
av_assert0
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition: avassert.h:40
FF_VK_REP_FLOAT
@ FF_VK_REP_FLOAT
Definition: vulkan.h:376
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:127
FFVulkanShader::stage
VkPipelineStageFlags stage
Definition: vulkan.h:193
AV_PIX_FMT_YUV420P16
#define AV_PIX_FMT_YUV420P16
Definition: pixfmt.h:521
ctx
AVFormatContext * ctx
Definition: movenc.c:49
AV_PIX_FMT_GRAY14
#define AV_PIX_FMT_GRAY14
Definition: pixfmt.h:493
av_frame_clone
AVFrame * av_frame_clone(const AVFrame *src)
Create a new frame that references the same data as src.
Definition: frame.c:610
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:551
AV_PIX_FMT_RGBF32
#define AV_PIX_FMT_RGBF32
Definition: pixfmt.h:587
AV_PIX_FMT_YUV420P
@ AV_PIX_FMT_YUV420P
planar YUV 4:2:0, 12bpp, (1 Cr & Cb sample per 2x2 Y samples)
Definition: pixfmt.h:73
ff_vk_exec_pool_free
void ff_vk_exec_pool_free(FFVulkanContext *s, FFVkExecPool *pool)
Definition: vulkan.c:233
ImageViewCtx::views
VkImageView views[]
Definition: vulkan.c:1487
map_fmt_to_rep
static VkFormat map_fmt_to_rep(VkFormat fmt, enum FFVkShaderRepFormat rep_fmt)
Definition: vulkan.c:1502
AV_PIX_FMT_GRAYF32
#define AV_PIX_FMT_GRAYF32
Definition: pixfmt.h:546
FFVkExecContext::frame_update
uint8_t * frame_update
Definition: vulkan.h:164
FFVkExecContext::query_idx
int query_idx
Definition: vulkan.h:123
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:257
FFVkExecContext::parent
const struct FFVkExecPool * parent
Definition: vulkan.h:104
AV_PIX_FMT_GRAY10
#define AV_PIX_FMT_GRAY10
Definition: pixfmt.h:491
if
if(ret)
Definition: filter_design.txt:179
AV_PIX_FMT_GBRP16
#define AV_PIX_FMT_GBRP16
Definition: pixfmt.h:529
FFVulkanShaderData::desc_set_buf
FFVulkanDescriptorSetData * desc_set_buf
Definition: vulkan.h:236
AV_PIX_FMT_RGBA64
#define AV_PIX_FMT_RGBA64
Definition: pixfmt.h:500
LIBAVUTIL_VERSION_INT
#define LIBAVUTIL_VERSION_INT
Definition: version.h:85
ff_vk_shader_rep_fmt
const char * ff_vk_shader_rep_fmt(enum AVPixelFormat pix_fmt, enum FFVkShaderRepFormat rep_fmt)
Definition: vulkan.c:1322
AVClass
Describe the class of an AVClass context structure.
Definition: log.h:75
FFVkExecContext::sw_frame_deps_alloc_size
unsigned int sw_frame_deps_alloc_size
Definition: vulkan.h:137
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:877
FFVkExecContext::sem_sig_val_dst_alloc
unsigned int sem_sig_val_dst_alloc
Definition: vulkan.h:149
descriptor_props::mem_quali
int mem_quali
Definition: vulkan.c:2062
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:46
FFVkExecContext::access_dst_alloc
unsigned int access_dst_alloc
Definition: vulkan.h:156
AV_PIX_FMT_YUYV422
@ AV_PIX_FMT_YUYV422
packed YUV 4:2:2, 16bpp, Y0 Cb Y1 Cr
Definition: pixfmt.h:74
FFVulkanDescriptorSet::singular
int singular
Definition: vulkan.h:179
FFVkExecContext::sem_sig_cnt
int sem_sig_cnt
Definition: vulkan.h:146
TempSyncCtx::sem
VkSemaphore sem[]
Definition: vulkan.c:610
load_enabled_qfs
static void load_enabled_qfs(FFVulkanContext *s)
Definition: vulkan.c:87
AV_PIX_FMT_P410
#define AV_PIX_FMT_P410
Definition: pixfmt.h:578
TempSyncCtx
Definition: vulkan.c:608
flush
void(* flush)(AVBSFContext *ctx)
Definition: dts2pts.c:370
FFVkExecContext::qi
int qi
Definition: vulkan.h:111
FFVkExecContext::had_submission
int had_submission
Definition: vulkan.h:106
FFVkBuffer::size
size_t size
Definition: vulkan.h:91
descriptor_props::dim_needed
int dim_needed
Definition: vulkan.c:2063
FFVkExecPool::nb_queries
int nb_queries
Definition: vulkan.h:258
AV_PIX_FMT_BGR0
@ AV_PIX_FMT_BGR0
packed BGR 8:8:8, 32bpp, BGRXBGRX... X=unused/undefined
Definition: pixfmt.h:265
AV_PIX_FMT_YUV422P10
#define AV_PIX_FMT_YUV422P10
Definition: pixfmt.h:511
FFVkBuffer::mapped_mem
uint8_t * mapped_mem
Definition: vulkan.h:99
AV_PIX_FMT_GRAY8
@ AV_PIX_FMT_GRAY8
Y , 8bpp.
Definition: pixfmt.h:81
FFVulkanContext
Definition: vulkan.h:266
FFVulkanShader::nb_descriptor_sets
int nb_descriptor_sets
Definition: vulkan.h:212
FFVulkanShader::bound_buffer_indices
uint32_t * bound_buffer_indices
Definition: vulkan.h:216
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:1864
GLSLA
#define GLSLA(...)
Definition: vulkan.h:49
index
int index
Definition: gxfenc.c:90
FFVkExecContext::query_data
void * query_data
Definition: vulkan.h:122
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:2384
usage
const char * usage
Definition: floatimg_cmp.c:60
AV_PIX_FMT_X2BGR10
#define AV_PIX_FMT_X2BGR10
Definition: pixfmt.h:575
f
f
Definition: af_crystalizer.c:122
FFVkExecContext::layout_dst
VkImageLayout * layout_dst
Definition: vulkan.h:158
destroy_imageviews
static void destroy_imageviews(void *opaque, uint8_t *data)
Definition: vulkan.c:1490
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:162
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:2528
FFVulkanDescriptorSetBinding
Definition: vulkan.h:75
FFVulkanShaderData::nb_descriptor_sets
int nb_descriptor_sets
Definition: vulkan.h:233
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
AV_PIX_FMT_P012
#define AV_PIX_FMT_P012
Definition: pixfmt.h:564
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
vulkan.h
for
for(k=2;k<=8;++k)
Definition: h264pred_template.c:424
print
static void print(AVTreeNode *t, int depth)
Definition: tree.c:45
AV_PIX_FMT_GBRPF32
#define AV_PIX_FMT_GBRPF32
Definition: pixfmt.h:542
AV_PIX_FMT_YUV422P12
#define AV_PIX_FMT_YUV422P12
Definition: pixfmt.h:515
AV_PIX_FMT_RGB48
#define AV_PIX_FMT_RGB48
Definition: pixfmt.h:496
FFVulkanShader::desc_pool_size
VkDescriptorPoolSize * desc_pool_size
Definition: vulkan.h:220
size
int size
Definition: twinvq_data.h:10344
ff_vk_exec_add_dep_sw_frame
int ff_vk_exec_add_dep_sw_frame(FFVulkanContext *s, FFVkExecContext *e, AVFrame *f)
Definition: vulkan.c:575
AV_NUM_DATA_POINTERS
#define AV_NUM_DATA_POINTERS
Definition: frame.h:411
FF_VK_EXT_PUSH_DESCRIPTOR
#define FF_VK_EXT_PUSH_DESCRIPTOR
Definition: vulkan_functions.h:47
FFVkExecContext::nb_frame_deps
int nb_frame_deps
Definition: vulkan.h:133
FFVulkanShader
Definition: vulkan.h:182
AV_PIX_FMT_YUV444P12
#define AV_PIX_FMT_YUV444P12
Definition: pixfmt.h:517
FFVulkanShader::pipeline_layout
VkPipelineLayout pipeline_layout
Definition: vulkan.h:204
FFVkExecContext::sem_sig_val_dst_cnt
int sem_sig_val_dst_cnt
Definition: vulkan.h:150
update_set_pool_write
static void update_set_pool_write(FFVulkanContext *s, FFVkExecContext *e, FFVulkanShader *shd, int set, VkWriteDescriptorSet *write_info)
Definition: vulkan.c:2357
AV_PIX_FMT_NV16
@ AV_PIX_FMT_NV16
interleaved chroma YUV 4:2:2, 16bpp, (1 Cr & Cb sample per 2x1 Y samples)
Definition: pixfmt.h:198
FFVkBuffer::flags
VkMemoryPropertyFlagBits flags
Definition: vulkan.h:90
AV_PIX_FMT_Y212
#define AV_PIX_FMT_Y212
Definition: pixfmt.h:568
AVVkFrame::queue_family
uint32_t queue_family[AV_NUM_DATA_POINTERS]
Queue family of the images.
Definition: hwcontext_vulkan.h:366
AVVulkanDeviceQueueFamily::idx
int idx
Definition: hwcontext_vulkan.h:35
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:102
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:2449
AV_PIX_FMT_RGB0
@ AV_PIX_FMT_RGB0
packed RGB 8:8:8, 32bpp, RGBXRGBX... X=unused/undefined
Definition: pixfmt.h:263
AV_PIX_FMT_P216
#define AV_PIX_FMT_P216
Definition: pixfmt.h:581
version
version
Definition: libkvazaar.c:321
AV_PIX_FMT_P210
#define AV_PIX_FMT_P210
Definition: pixfmt.h:577
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:1301
destroy_tmp_semaphores
static void destroy_tmp_semaphores(void *opaque, uint8_t *data)
Definition: vulkan.c:613
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:142
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:109
AV_PIX_FMT_UYVA
@ AV_PIX_FMT_UYVA
packed UYVA 4:4:4:4, 32bpp (1 Cr & Cb sample per 1x1 Y & A samples), UYVAUYVA...
Definition: pixfmt.h:444
descriptor_props
Definition: vulkan.c:2058
ff_vk_exec_start
int ff_vk_exec_start(FFVulkanContext *s, FFVkExecContext *e)
Start/submit/wait an execution.
Definition: vulkan.c:489
FF_VK_EXT_RELAXED_EXTENDED_INSTR
#define FF_VK_EXT_RELAXED_EXTENDED_INSTR
Definition: vulkan_functions.h:48
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:256
FF_VK_REP_UINT
@ FF_VK_REP_UINT
Definition: vulkan.h:380
FFVulkanShaderData::desc_pool
VkDescriptorPool desc_pool
Definition: vulkan.h:241
VkFormat
enum VkFormat VkFormat
Definition: hwcontext_stub.c:25
FFVulkanShader::push_consts_num
int push_consts_num
Definition: vulkan.h:208
AV_PIX_FMT_GBRP12
#define AV_PIX_FMT_GBRP12
Definition: pixfmt.h:527
av_malloc_array
#define av_malloc_array(a, b)
Definition: tableprint_vlc.h:31
AV_PIX_FMT_NV24
@ AV_PIX_FMT_NV24
planar YUV 4:4:4, 24bpp, 1 plane for Y and 1 plane for the UV components, which are interleaved (firs...
Definition: pixfmt.h:371
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:1672
FFVkExecContext::layout_dst_alloc
unsigned int layout_dst_alloc
Definition: vulkan.h:159
FFVkExecPool::reg_shd
FFVulkanShaderData * reg_shd
Definition: vulkan.h:262
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:2004
ff_vk_unmap_buffer
static int ff_vk_unmap_buffer(FFVulkanContext *s, FFVkBuffer *buf, int flush)
Definition: vulkan.h:502
FFVkBuffer::mem
VkDeviceMemory mem
Definition: vulkan.h:89
AV_PIX_FMT_X2RGB10
#define AV_PIX_FMT_X2RGB10
Definition: pixfmt.h:574
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
FFVkExecContext::frame_locked_alloc_size
unsigned int frame_locked_alloc_size
Definition: vulkan.h:153
len
int len
Definition: vorbis_enc_data.h:426
AV_PIX_FMT_BGR565
#define AV_PIX_FMT_BGR565
Definition: pixfmt.h:502
filt
static const int8_t filt[NUMTAPS *2]
Definition: af_earwax.c:40
ff_vk_free_buf
void ff_vk_free_buf(FFVulkanContext *s, FFVkBuffer *buf)
Definition: vulkan.c:1142
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:755
ff_vk_exec_bind_shader
void ff_vk_exec_bind_shader(FFVulkanContext *s, FFVkExecContext *e, FFVulkanShader *shd)
Bind a shader.
Definition: vulkan.c:2538
FFVulkanDescriptorSet::binding_offset
VkDeviceSize * binding_offset
Definition: vulkan.h:175
AV_PIX_FMT_P016
#define AV_PIX_FMT_P016
Definition: pixfmt.h:565
AV_PIX_FMT_RGB565
#define AV_PIX_FMT_RGB565
Definition: pixfmt.h:497
FFVkExecContext::sem_wait_alloc
unsigned int sem_wait_alloc
Definition: vulkan.h:141
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
AV_PIX_FMT_0BGR
@ AV_PIX_FMT_0BGR
packed BGR 8:8:8, 32bpp, XBGRXBGR... X=unused/undefined
Definition: pixfmt.h:264
AV_PIX_FMT_NV12
@ AV_PIX_FMT_NV12
planar YUV 4:2:0, 12bpp, 1 plane for Y and 1 plane for the UV components, which are interleaved (firs...
Definition: pixfmt.h:96
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:184
ff_vk_create_imageviews
int ff_vk_create_imageviews(FFVulkanContext *s, FFVkExecContext *e, VkImageView views[AV_NUM_DATA_POINTERS], AVFrame *f, enum FFVkShaderRepFormat rep_fmt)
Create an imageview and add it as a dependency to an execution.
Definition: vulkan.c:1589
AVHWFramesContext::hwctx
void * hwctx
The format-specific data, allocated and freed automatically along with this context.
Definition: hwcontext.h:150
FFVkExecPool
Definition: vulkan.h:244
FFVkExecContext::frame_locked
uint8_t * frame_locked
Definition: vulkan.h:152
FFVkExecPool::query_data
void * query_data
Definition: vulkan.h:253
descriptor_props::buf_content
int buf_content
Definition: vulkan.c:2064
FFVkExecContext::sem_sig
VkSemaphoreSubmitInfo * sem_sig
Definition: vulkan.h:144
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:1231
ff_vk_qf_find
AVVulkanDeviceQueueFamily * ff_vk_qf_find(FFVulkanContext *s, VkQueueFlagBits dev_family, VkVideoCodecOperationFlagBitsKHR vid_ops)
Chooses an appropriate QF.
Definition: vulkan.c:220
AV_PIX_FMT_YUV420P12
#define AV_PIX_FMT_YUV420P12
Definition: pixfmt.h:514
FF_VK_EXT_DESCRIPTOR_BUFFER
#define FF_VK_EXT_DESCRIPTOR_BUFFER
Definition: vulkan_functions.h:41
AV_PIX_FMT_UYVY422
@ AV_PIX_FMT_UYVY422
packed YUV 4:2:2, 16bpp, Cb Y0 Cr Y1
Definition: pixfmt.h:88
FFVkExecContext::buf
VkCommandBuffer buf
Definition: vulkan.h:114
SIZE_SPECIFIER
#define SIZE_SPECIFIER
Definition: internal.h:129
FFVulkanShader::desc_set
FFVulkanDescriptorSet * desc_set
Definition: vulkan.h:211
free_data_buf
static void free_data_buf(void *opaque, uint8_t *data)
Definition: vulkan.c:1157
GLSLF
#define GLSLF(N, S,...)
Definition: vulkan.h:54
AV_PIX_FMT_GBRAPF32
#define AV_PIX_FMT_GBRAPF32
Definition: pixfmt.h:543
FFVulkanShader::object
VkShaderEXT object
Definition: vulkan.h:200
ref
static int ref[MAX_W *MAX_W]
Definition: jpeg2000dwt.c:117
AV_PIX_FMT_RGBAF32
#define AV_PIX_FMT_RGBAF32
Definition: pixfmt.h:588
AV_PIX_FMT_YUV444P
@ AV_PIX_FMT_YUV444P
planar YUV 4:4:4, 24bpp, (1 Cr & Cb sample per 1x1 Y samples)
Definition: pixfmt.h:78
AV_PIX_FMT_P010
#define AV_PIX_FMT_P010
Definition: pixfmt.h:563
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
AV_PIX_FMT_YUV422P
@ AV_PIX_FMT_YUV422P
planar YUV 4:2:2, 16bpp, (1 Cr & Cb sample per 2x1 Y samples)
Definition: pixfmt.h:77
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:249
FFVkExecContext::sw_frame_deps
AVFrame ** sw_frame_deps
Definition: vulkan.h:136
REPS_FMT_PACK
#define REPS_FMT_PACK(fmt, num)
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:1790
av_free
#define av_free(p)
Definition: tableprint_vlc.h:33
ff_vk_count_images
static int ff_vk_count_images(AVVkFrame *f)
Definition: vulkan.h:312
ff_vk_exec_discard_deps
void ff_vk_exec_discard_deps(FFVulkanContext *s, FFVkExecContext *e)
Definition: vulkan.c:521
FFALIGN
#define FFALIGN(x, a)
Definition: macros.h:78
AV_PIX_FMT_P416
#define AV_PIX_FMT_P416
Definition: pixfmt.h:582
ff_vk_init_sampler
int ff_vk_init_sampler(FFVulkanContext *s, VkSampler *sampler, int unnorm_coords, VkFilter filt)
Create a sampler.
Definition: vulkan.c:1252
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:128
FFVkExecContext::buf_deps
AVBufferRef ** buf_deps
Definition: vulkan.h:126
FFVkBuffer
Definition: vulkan.h:87
ff_vk_exec_submit
int ff_vk_exec_submit(FFVulkanContext *s, FFVkExecContext *e)
Definition: vulkan.c:811
AV_PIX_FMT_XV36
#define AV_PIX_FMT_XV36
Definition: pixfmt.h:571
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
AVVulkanDeviceQueueFamily
Definition: hwcontext_vulkan.h:33
FFVkExecPool::qd_size
size_t qd_size
Definition: vulkan.h:259
AV_PIX_FMT_P412
#define AV_PIX_FMT_P412
Definition: pixfmt.h:580
FFVulkanDescriptorSet
Definition: vulkan.h:168
atomic_init
#define atomic_init(obj, value)
Definition: stdatomic.h:33
AV_PIX_FMT_GRAY12
#define AV_PIX_FMT_GRAY12
Definition: pixfmt.h:492
FFVkExecPool::query_results
int query_results
Definition: vulkan.h:254
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:1899
FFVkExecContext::sem_sig_val_dst
uint64_t ** sem_sig_val_dst
Definition: vulkan.h:148
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:2329
CASE
#define CASE(VAL)
FFVulkanFunctions
Definition: vulkan_functions.h:263
FFVkExecPool::pool_size
int pool_size
Definition: vulkan.h:250
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:248
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:1178
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:1055
FFVkExecContext::idx
uint32_t idx
Definition: vulkan.h:103
src
#define src
Definition: vp8dsp.c:248
FFVulkanShader::lg_size
int lg_size[3]
Definition: vulkan.h:190
REPS_FMT
#define REPS_FMT(fmt)
FFVkExecContext::access_dst
VkAccessFlagBits * access_dst
Definition: vulkan.h:155