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