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