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