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