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