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