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