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