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