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