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