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  /* Buffer usage flags corresponding to buffer descriptor types */
993  const VkBufferUsageFlags desc_usage =
994  VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT |
995  VK_BUFFER_USAGE_STORAGE_BUFFER_BIT |
996  VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT |
997  VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT;
998 
999  if ((s->extensions & FF_VK_EXT_DESCRIPTOR_BUFFER) && (usage & desc_usage))
1000  usage |= VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT;
1001 
1002  VkBufferCreateInfo buf_spawn = {
1003  .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
1004  .pNext = pNext,
1005  .usage = usage,
1006  .sharingMode = VK_SHARING_MODE_EXCLUSIVE,
1007  .size = flags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT ?
1008  FFALIGN(size, s->props.properties.limits.minMemoryMapAlignment) :
1009  size,
1010  };
1011 
1012  VkMemoryAllocateFlagsInfo alloc_flags = {
1013  .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_FLAGS_INFO,
1014  .flags = VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT,
1015  };
1016  VkBufferMemoryRequirementsInfo2 req_desc = {
1017  .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_REQUIREMENTS_INFO_2,
1018  };
1019  VkMemoryDedicatedAllocateInfo ded_alloc = {
1020  .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO,
1021  .pNext = alloc_pNext,
1022  };
1023  VkMemoryDedicatedRequirements ded_req = {
1024  .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS,
1025  };
1026  VkMemoryRequirements2 req = {
1027  .sType = VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2,
1028  .pNext = &ded_req,
1029  };
1030 
1031  av_log(s, AV_LOG_DEBUG, "Creating a buffer of %"SIZE_SPECIFIER" bytes, "
1032  "usage: 0x%x, flags: 0x%x\n",
1033  size, usage, flags);
1034 
1035  ret = vk->CreateBuffer(s->hwctx->act_dev, &buf_spawn, s->hwctx->alloc, &buf->buf);
1036  if (ret != VK_SUCCESS) {
1037  av_log(s, AV_LOG_ERROR, "Failed to create buffer: %s\n",
1038  ff_vk_ret2str(ret));
1039  return AVERROR_EXTERNAL;
1040  }
1041 
1042  req_desc.buffer = buf->buf;
1043 
1044  vk->GetBufferMemoryRequirements2(s->hwctx->act_dev, &req_desc, &req);
1045 
1046  /* In case the implementation prefers/requires dedicated allocation */
1047  use_ded_mem = ded_req.prefersDedicatedAllocation |
1048  ded_req.requiresDedicatedAllocation;
1049  if (use_ded_mem) {
1050  ded_alloc.buffer = buf->buf;
1051  ded_alloc.pNext = alloc_pNext;
1052  alloc_pNext = &ded_alloc;
1053  }
1054 
1055  if (usage & VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT) {
1056  alloc_flags.pNext = alloc_pNext;
1057  alloc_pNext = &alloc_flags;
1058  }
1059 
1060  err = ff_vk_alloc_mem(s, &req.memoryRequirements, flags, alloc_pNext,
1061  &buf->flags, &buf->mem);
1062  if (err)
1063  return err;
1064 
1065  ret = vk->BindBufferMemory(s->hwctx->act_dev, buf->buf, buf->mem, 0);
1066  if (ret != VK_SUCCESS) {
1067  av_log(s, AV_LOG_ERROR, "Failed to bind memory to buffer: %s\n",
1068  ff_vk_ret2str(ret));
1069  return AVERROR_EXTERNAL;
1070  }
1071 
1072  if (usage & VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT) {
1073  VkBufferDeviceAddressInfo address_info = {
1074  .sType = VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO,
1075  .buffer = buf->buf,
1076  };
1077  buf->address = vk->GetBufferDeviceAddress(s->hwctx->act_dev, &address_info);
1078  }
1079 
1080  buf->size = size;
1081 
1082  return 0;
1083 }
1084 
1085 int ff_vk_map_buffers(FFVulkanContext *s, FFVkBuffer **buf, uint8_t *mem[],
1086  int nb_buffers, int invalidate)
1087 {
1088  VkResult ret;
1089  FFVulkanFunctions *vk = &s->vkfn;
1090  VkMappedMemoryRange inval_list[64];
1091  int inval_count = 0;
1092 
1093  for (int i = 0; i < nb_buffers; i++) {
1094  void *dst;
1095  ret = vk->MapMemory(s->hwctx->act_dev, buf[i]->mem, 0,
1096  VK_WHOLE_SIZE, 0, &dst);
1097  if (ret != VK_SUCCESS) {
1098  av_log(s, AV_LOG_ERROR, "Failed to map buffer memory: %s\n",
1099  ff_vk_ret2str(ret));
1100  return AVERROR_EXTERNAL;
1101  }
1102  mem[i] = buf[i]->mapped_mem = dst;
1103  }
1104 
1105  if (!invalidate)
1106  return 0;
1107 
1108  for (int i = 0; i < nb_buffers; i++) {
1109  const VkMappedMemoryRange ival_buf = {
1110  .sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,
1111  .memory = buf[i]->mem,
1112  .size = VK_WHOLE_SIZE,
1113  };
1114  if (buf[i]->flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)
1115  continue;
1116  inval_list[inval_count++] = ival_buf;
1117  }
1118 
1119  if (inval_count) {
1120  ret = vk->InvalidateMappedMemoryRanges(s->hwctx->act_dev, inval_count,
1121  inval_list);
1122  if (ret != VK_SUCCESS) {
1123  av_log(s, AV_LOG_ERROR, "Failed to invalidate memory: %s\n",
1124  ff_vk_ret2str(ret));
1125  return AVERROR_EXTERNAL;
1126  }
1127  }
1128 
1129  return 0;
1130 }
1131 
1132 int ff_vk_unmap_buffers(FFVulkanContext *s, FFVkBuffer **buf, int nb_buffers,
1133  int flush)
1134 {
1135  int err = 0;
1136  VkResult ret;
1137  FFVulkanFunctions *vk = &s->vkfn;
1138  VkMappedMemoryRange flush_list[64];
1139  int flush_count = 0;
1140 
1141  if (flush) {
1142  for (int i = 0; i < nb_buffers; i++) {
1143  const VkMappedMemoryRange flush_buf = {
1144  .sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,
1145  .memory = buf[i]->mem,
1146  .size = VK_WHOLE_SIZE,
1147  };
1148 
1149  av_assert0(!buf[i]->host_ref);
1150  if (buf[i]->flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)
1151  continue;
1152  flush_list[flush_count++] = flush_buf;
1153  }
1154  }
1155 
1156  if (flush_count) {
1157  ret = vk->FlushMappedMemoryRanges(s->hwctx->act_dev, flush_count,
1158  flush_list);
1159  if (ret != VK_SUCCESS) {
1160  av_log(s, AV_LOG_ERROR, "Failed to flush memory: %s\n",
1161  ff_vk_ret2str(ret));
1162  err = AVERROR_EXTERNAL; /* We still want to try to unmap them */
1163  }
1164  }
1165 
1166  for (int i = 0; i < nb_buffers; i++) {
1167  vk->UnmapMemory(s->hwctx->act_dev, buf[i]->mem);
1168  buf[i]->mapped_mem = NULL;
1169  }
1170 
1171  return err;
1172 }
1173 
1175 {
1176  FFVulkanFunctions *vk = &s->vkfn;
1177 
1178  if (!buf || !s->hwctx)
1179  return;
1180 
1181  if (buf->mapped_mem && !buf->host_ref)
1182  ff_vk_unmap_buffer(s, buf, 0);
1183  if (buf->buf != VK_NULL_HANDLE)
1184  vk->DestroyBuffer(s->hwctx->act_dev, buf->buf, s->hwctx->alloc);
1185  if (buf->mem != VK_NULL_HANDLE)
1186  vk->FreeMemory(s->hwctx->act_dev, buf->mem, s->hwctx->alloc);
1187  if (buf->host_ref)
1188  av_buffer_unref(&buf->host_ref);
1189 
1190  buf->buf = VK_NULL_HANDLE;
1191  buf->mem = VK_NULL_HANDLE;
1192  buf->mapped_mem = NULL;
1193 }
1194 
1195 static void free_data_buf(void *opaque, uint8_t *data)
1196 {
1197  FFVulkanContext *ctx = opaque;
1198  FFVkBuffer *buf = (FFVkBuffer *)data;
1199  ff_vk_free_buf(ctx, buf);
1200  av_free(data);
1201 }
1202 
1203 static AVBufferRef *alloc_data_buf(void *opaque, size_t size)
1204 {
1205  AVBufferRef *ref;
1206  uint8_t *buf = av_mallocz(size);
1207  if (!buf)
1208  return NULL;
1209 
1210  ref = av_buffer_create(buf, size, free_data_buf, opaque, 0);
1211  if (!ref)
1212  av_free(buf);
1213  return ref;
1214 }
1215 
1217  AVBufferRef **buf, VkBufferUsageFlags usage,
1218  void *create_pNext, size_t size,
1219  VkMemoryPropertyFlagBits mem_props)
1220 {
1221  int err;
1222  AVBufferRef *ref;
1223  FFVkBuffer *data;
1224 
1225  *buf = NULL;
1226 
1227  if (!(*buf_pool)) {
1228  *buf_pool = av_buffer_pool_init2(sizeof(FFVkBuffer), ctx,
1229  alloc_data_buf, NULL);
1230  if (!(*buf_pool))
1231  return AVERROR(ENOMEM);
1232  }
1233 
1234  *buf = ref = av_buffer_pool_get(*buf_pool);
1235  if (!ref)
1236  return AVERROR(ENOMEM);
1237 
1238  data = (FFVkBuffer *)ref->data;
1239  data->stage = VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT;
1240  data->access = VK_ACCESS_2_NONE;
1241 
1242  if (data->size >= size)
1243  return 0;
1244 
1246  memset(data, 0, sizeof(*data));
1247 
1248  err = ff_vk_create_buf(ctx, data, size,
1249  create_pNext, NULL, usage,
1250  mem_props);
1251  if (err < 0) {
1252  av_buffer_unref(&ref);
1253  *buf = NULL;
1254  return err;
1255  }
1256 
1257  if (mem_props & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) {
1258  err = ff_vk_map_buffer(ctx, data, &data->mapped_mem, 0);
1259  if (err < 0) {
1260  av_buffer_unref(&ref);
1261  *buf = NULL;
1262  return err;
1263  }
1264  }
1265 
1266  return 0;
1267 }
1268 
1270  FFVkBuffer *vkb, VkBufferUsageFlags usage,
1271  size_t size,
1272  VkExternalMemoryBufferCreateInfo *create_desc,
1273  VkImportMemoryHostPointerInfoEXT *import_desc,
1274  VkMemoryHostPointerPropertiesEXT props)
1275 {
1276  int err;
1277  VkResult ret;
1278  FFVulkanFunctions *vk = &s->vkfn;
1279 
1280  VkBufferCreateInfo buf_spawn = {
1281  .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
1282  .pNext = create_desc,
1283  .usage = usage,
1284  .sharingMode = VK_SHARING_MODE_EXCLUSIVE,
1285  .size = size,
1286  };
1287  VkMemoryRequirements req = {
1288  .size = size,
1289  .alignment = s->hprops.minImportedHostPointerAlignment,
1290  .memoryTypeBits = props.memoryTypeBits,
1291  };
1292 
1293  err = ff_vk_alloc_mem(s, &req,
1294  VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT,
1295  import_desc, &vkb->flags, &vkb->mem);
1296  if (err < 0)
1297  return err;
1298 
1299  ret = vk->CreateBuffer(s->hwctx->act_dev, &buf_spawn, s->hwctx->alloc, &vkb->buf);
1300  if (ret != VK_SUCCESS) {
1301  vk->FreeMemory(s->hwctx->act_dev, vkb->mem, s->hwctx->alloc);
1302  return AVERROR_EXTERNAL;
1303  }
1304 
1305  ret = vk->BindBufferMemory(s->hwctx->act_dev, vkb->buf, vkb->mem, 0);
1306  if (ret != VK_SUCCESS) {
1307  vk->FreeMemory(s->hwctx->act_dev, vkb->mem, s->hwctx->alloc);
1308  vk->DestroyBuffer(s->hwctx->act_dev, vkb->buf, s->hwctx->alloc);
1309  return AVERROR_EXTERNAL;
1310  }
1311 
1312  return 0;
1313 }
1314 
1315 static void destroy_avvkbuf(void *opaque, uint8_t *data)
1316 {
1317  FFVulkanContext *s = opaque;
1318  FFVkBuffer *buf = (FFVkBuffer *)data;
1319  ff_vk_free_buf(s, buf);
1320  av_free(buf);
1321 }
1322 
1324  uint8_t *src_data, const AVBufferRef *src_buf,
1325  VkBufferUsageFlags usage)
1326 {
1327  int err;
1328  VkResult ret;
1329  FFVulkanFunctions *vk = &s->vkfn;
1330 
1331  VkExternalMemoryBufferCreateInfo create_desc = {
1332  .sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO,
1333  .handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT,
1334  };
1335  VkMemoryAllocateFlagsInfo alloc_flags = {
1336  .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_FLAGS_INFO,
1337  .flags = VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT,
1338  };
1339  VkImportMemoryHostPointerInfoEXT import_desc = {
1340  .sType = VK_STRUCTURE_TYPE_IMPORT_MEMORY_HOST_POINTER_INFO_EXT,
1341  .handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT,
1342  .pNext = usage & VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT ? &alloc_flags : NULL,
1343  };
1344  VkMemoryHostPointerPropertiesEXT props;
1345 
1346  AVBufferRef *ref;
1347  FFVkBuffer *vkb;
1348  size_t offs;
1349  size_t buffer_size;
1350 
1351  *dst = NULL;
1352 
1353  /* Get the previous point at which mapping was possible and use it */
1354  offs = (uintptr_t)src_data % s->hprops.minImportedHostPointerAlignment;
1355  import_desc.pHostPointer = src_data - offs;
1356 
1357  props = (VkMemoryHostPointerPropertiesEXT) {
1358  VK_STRUCTURE_TYPE_MEMORY_HOST_POINTER_PROPERTIES_EXT,
1359  };
1360  ret = vk->GetMemoryHostPointerPropertiesEXT(s->hwctx->act_dev,
1361  import_desc.handleType,
1362  import_desc.pHostPointer,
1363  &props);
1364  if (!(ret == VK_SUCCESS && props.memoryTypeBits))
1365  return AVERROR(EINVAL);
1366 
1367  /* Ref the source buffer */
1368  ref = av_buffer_ref(src_buf);
1369  if (!ref)
1370  return AVERROR(ENOMEM);
1371 
1372  /* Add the offset at the start, which gets ignored */
1373  buffer_size = offs + src_buf->size;
1374  buffer_size = FFALIGN(buffer_size, s->props.properties.limits.minMemoryMapAlignment);
1375  buffer_size = FFALIGN(buffer_size, s->hprops.minImportedHostPointerAlignment);
1376 
1377  /* Create a buffer struct */
1378  vkb = av_mallocz(sizeof(*vkb));
1379  if (!vkb) {
1380  av_buffer_unref(&ref);
1381  return AVERROR(ENOMEM);
1382  }
1383 
1384  err = create_mapped_buffer(s, vkb, usage,
1385  buffer_size, &create_desc, &import_desc,
1386  props);
1387  if (err < 0) {
1388  av_buffer_unref(&ref);
1389  av_free(vkb);
1390  return err;
1391  }
1392 
1393  if (usage & VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT) {
1394  VkBufferDeviceAddressInfo address_info = {
1395  .sType = VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO,
1396  .buffer = vkb->buf,
1397  };
1398  vkb->address = vk->GetBufferDeviceAddress(s->hwctx->act_dev, &address_info);
1399  }
1400 
1401  vkb->host_ref = ref;
1402  vkb->virtual_offset = offs;
1403  vkb->address += offs;
1404  vkb->mapped_mem = src_data;
1405  vkb->size = buffer_size - offs;
1406  vkb->flags |= VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
1407 
1408  /* Create a ref */
1409  *dst = av_buffer_create((uint8_t *)vkb, sizeof(*vkb),
1410  destroy_avvkbuf, s, 0);
1411  if (!(*dst)) {
1412  destroy_avvkbuf(s, (uint8_t *)vkb);
1413  *dst = NULL;
1414  return AVERROR(ENOMEM);
1415  }
1416 
1417  return 0;
1418 }
1419 
1421  VkShaderStageFlagBits stage)
1422 {
1423  VkPushConstantRange *pc;
1424 
1426  sizeof(*shd->push_consts),
1427  shd->push_consts_num + 1);
1428  if (!shd->push_consts)
1429  return AVERROR(ENOMEM);
1430 
1431  pc = &shd->push_consts[shd->push_consts_num++];
1432  memset(pc, 0, sizeof(*pc));
1433 
1434  pc->stageFlags = stage;
1435  pc->offset = offset;
1436  pc->size = size;
1437 
1438  return 0;
1439 }
1440 
1441 int ff_vk_init_sampler(FFVulkanContext *s, VkSampler *sampler,
1442  int unnorm_coords, VkFilter filt)
1443 {
1444  VkResult ret;
1445  FFVulkanFunctions *vk = &s->vkfn;
1446 
1447  VkSamplerCreateInfo sampler_info = {
1448  .sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,
1449  .magFilter = filt,
1450  .minFilter = sampler_info.magFilter,
1451  .mipmapMode = unnorm_coords ? VK_SAMPLER_MIPMAP_MODE_NEAREST :
1452  VK_SAMPLER_MIPMAP_MODE_LINEAR,
1453  .addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
1454  .addressModeV = sampler_info.addressModeU,
1455  .addressModeW = sampler_info.addressModeU,
1456  .anisotropyEnable = VK_FALSE,
1457  .compareOp = VK_COMPARE_OP_NEVER,
1458  .borderColor = VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK,
1459  .unnormalizedCoordinates = unnorm_coords,
1460  };
1461 
1462  ret = vk->CreateSampler(s->hwctx->act_dev, &sampler_info,
1463  s->hwctx->alloc, sampler);
1464  if (ret != VK_SUCCESS) {
1465  av_log(s, AV_LOG_ERROR, "Unable to init sampler: %s\n",
1466  ff_vk_ret2str(ret));
1467  return AVERROR_EXTERNAL;
1468  }
1469 
1470  return 0;
1471 }
1472 
1473 VkImageAspectFlags ff_vk_aspect_flag(AVFrame *f, int p)
1474 {
1475  AVVkFrame *vkf = (AVVkFrame *)f->data[0];
1476  AVHWFramesContext *hwfc = (AVHWFramesContext *)f->hw_frames_ctx->data;
1477  int nb_images = ff_vk_count_images(vkf);
1478  int nb_planes = av_pix_fmt_count_planes(hwfc->sw_format);
1479 
1480  static const VkImageAspectFlags plane_aspect[] = { VK_IMAGE_ASPECT_PLANE_0_BIT,
1481  VK_IMAGE_ASPECT_PLANE_1_BIT,
1482  VK_IMAGE_ASPECT_PLANE_2_BIT, };
1483 
1484  if (ff_vk_mt_is_np_rgb(hwfc->sw_format) || (nb_planes == nb_images))
1485  return VK_IMAGE_ASPECT_COLOR_BIT;
1486 
1487  return plane_aspect[p];
1488 }
1489 
1491 {
1508  return 1;
1509  return 0;
1510 }
1511 
1512 void ff_vk_set_perm(enum AVPixelFormat pix_fmt, int lut[4], int inv)
1513 {
1514  switch (pix_fmt) {
1515  case AV_PIX_FMT_GBRP:
1516  case AV_PIX_FMT_GBRAP:
1517  case AV_PIX_FMT_GBRAP10:
1518  case AV_PIX_FMT_GBRAP12:
1519  case AV_PIX_FMT_GBRAP14:
1520  case AV_PIX_FMT_GBRAP16:
1521  case AV_PIX_FMT_GBRP10:
1522  case AV_PIX_FMT_GBRP12:
1523  case AV_PIX_FMT_GBRP14:
1524  case AV_PIX_FMT_GBRP16:
1525  case AV_PIX_FMT_GBRPF32:
1526  case AV_PIX_FMT_GBRAP32:
1527  case AV_PIX_FMT_GBRAPF32:
1528  lut[0] = 1;
1529  lut[1] = 2;
1530  lut[2] = 0;
1531  lut[3] = 3;
1532  break;
1533  default:
1534  lut[0] = 0;
1535  lut[1] = 1;
1536  lut[2] = 2;
1537  lut[3] = 3;
1538  break;
1539  }
1540 
1541  if (inv) {
1542  int lut_tmp[4] = { lut[0], lut[1], lut[2], lut[3] };
1543  for (int i = 0; i < 4; i++)
1544  lut[lut_tmp[i]] = i;
1545  }
1546 
1547  return;
1548 }
1549 
1551  enum FFVkShaderRepFormat rep_fmt)
1552 {
1553  switch (pix_fmt) {
1554  case AV_PIX_FMT_RGBA:
1555  case AV_PIX_FMT_BGRA:
1556  case AV_PIX_FMT_RGB24:
1557  case AV_PIX_FMT_BGR24:
1558  case AV_PIX_FMT_BGR0:
1559  case AV_PIX_FMT_RGB0:
1560  case AV_PIX_FMT_RGB565:
1561  case AV_PIX_FMT_BGR565:
1562  case AV_PIX_FMT_UYVA:
1563  case AV_PIX_FMT_YUYV422:
1564  case AV_PIX_FMT_UYVY422: {
1565  const char *rep_tab[] = {
1566  [FF_VK_REP_NATIVE] = "rgba8ui",
1567  [FF_VK_REP_FLOAT] = "rgba8",
1568  [FF_VK_REP_INT] = "rgba8i",
1569  [FF_VK_REP_UINT] = "rgba8ui",
1570  };
1571  return rep_tab[rep_fmt];
1572  }
1573  case AV_PIX_FMT_X2RGB10:
1574  case AV_PIX_FMT_X2BGR10:
1575  case AV_PIX_FMT_Y210:
1576  case AV_PIX_FMT_XV30: {
1577  const char *rep_tab[] = {
1578  [FF_VK_REP_NATIVE] = "rgb10_a2ui",
1579  [FF_VK_REP_FLOAT] = "rgb10_a2",
1580  [FF_VK_REP_INT] = NULL,
1581  [FF_VK_REP_UINT] = "rgb10_a2ui",
1582  };
1583  return rep_tab[rep_fmt];
1584  }
1585  case AV_PIX_FMT_RGB48:
1586  case AV_PIX_FMT_RGBA64:
1587  case AV_PIX_FMT_Y212:
1588  case AV_PIX_FMT_Y216:
1589  case AV_PIX_FMT_XV36:
1590  case AV_PIX_FMT_XV48: {
1591  const char *rep_tab[] = {
1592  [FF_VK_REP_NATIVE] = "rgba16ui",
1593  [FF_VK_REP_FLOAT] = "rgba16",
1594  [FF_VK_REP_INT] = "rgba16i",
1595  [FF_VK_REP_UINT] = "rgba16ui",
1596  };
1597  return rep_tab[rep_fmt];
1598  }
1599  case AV_PIX_FMT_RGBF32:
1600  case AV_PIX_FMT_RGBAF32: {
1601  const char *rep_tab[] = {
1602  [FF_VK_REP_NATIVE] = "rgba32f",
1603  [FF_VK_REP_FLOAT] = "rgba32f",
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_RGB96:
1610  case AV_PIX_FMT_RGBA128: {
1611  const char *rep_tab[] = {
1612  [FF_VK_REP_NATIVE] = "rgba32ui",
1613  [FF_VK_REP_FLOAT] = NULL,
1614  [FF_VK_REP_INT] = "rgba32i",
1615  [FF_VK_REP_UINT] = "rgba32ui",
1616  };
1617  return rep_tab[rep_fmt];
1618  }
1619  case AV_PIX_FMT_GBRP:
1620  case AV_PIX_FMT_GRAY8:
1621  case AV_PIX_FMT_GBRAP:
1622  case AV_PIX_FMT_YUV420P:
1623  case AV_PIX_FMT_YUV422P:
1624  case AV_PIX_FMT_YUV444P:
1625  case AV_PIX_FMT_YUVA420P:
1626  case AV_PIX_FMT_YUVA422P:
1627  case AV_PIX_FMT_YUVA444P: {
1628  const char *rep_tab[] = {
1629  [FF_VK_REP_NATIVE] = "r8ui",
1630  [FF_VK_REP_FLOAT] = "r8",
1631  [FF_VK_REP_INT] = "r8i",
1632  [FF_VK_REP_UINT] = "r8ui",
1633  };
1634  return rep_tab[rep_fmt];
1635  };
1636  case AV_PIX_FMT_GRAY10:
1637  case AV_PIX_FMT_GRAY12:
1638  case AV_PIX_FMT_GRAY14:
1639  case AV_PIX_FMT_GRAY16:
1640  case AV_PIX_FMT_GBRAP10:
1641  case AV_PIX_FMT_GBRAP12:
1642  case AV_PIX_FMT_GBRAP14:
1643  case AV_PIX_FMT_GBRAP16:
1644  case AV_PIX_FMT_GBRP10:
1645  case AV_PIX_FMT_GBRP12:
1646  case AV_PIX_FMT_GBRP14:
1647  case AV_PIX_FMT_GBRP16:
1648  case AV_PIX_FMT_YUV420P10:
1649  case AV_PIX_FMT_YUV420P12:
1650  case AV_PIX_FMT_YUV420P16:
1651  case AV_PIX_FMT_YUV422P10:
1652  case AV_PIX_FMT_YUV422P12:
1653  case AV_PIX_FMT_YUV422P16:
1654  case AV_PIX_FMT_YUV444P10:
1655  case AV_PIX_FMT_YUV444P12:
1656  case AV_PIX_FMT_YUV444P16:
1657  case AV_PIX_FMT_YUVA420P10:
1658  case AV_PIX_FMT_YUVA420P16:
1659  case AV_PIX_FMT_YUVA422P10:
1660  case AV_PIX_FMT_YUVA422P12:
1661  case AV_PIX_FMT_YUVA422P16:
1662  case AV_PIX_FMT_YUVA444P10:
1663  case AV_PIX_FMT_YUVA444P12:
1664  case AV_PIX_FMT_YUVA444P16: {
1665  const char *rep_tab[] = {
1666  [FF_VK_REP_NATIVE] = "r16ui",
1667  [FF_VK_REP_FLOAT] = "r16f",
1668  [FF_VK_REP_INT] = "r16i",
1669  [FF_VK_REP_UINT] = "r16ui",
1670  };
1671  return rep_tab[rep_fmt];
1672  };
1673  case AV_PIX_FMT_GRAY32:
1674  case AV_PIX_FMT_GRAYF32:
1675  case AV_PIX_FMT_GBRPF32:
1676  case AV_PIX_FMT_GBRAPF32: {
1677  const char *rep_tab[] = {
1678  [FF_VK_REP_NATIVE] = "r32f",
1679  [FF_VK_REP_FLOAT] = "r32f",
1680  [FF_VK_REP_INT] = "r32i",
1681  [FF_VK_REP_UINT] = "r32ui",
1682  };
1683  return rep_tab[rep_fmt];
1684  };
1685  case AV_PIX_FMT_GBRAP32: {
1686  const char *rep_tab[] = {
1687  [FF_VK_REP_NATIVE] = "r32ui",
1688  [FF_VK_REP_FLOAT] = NULL,
1689  [FF_VK_REP_INT] = "r32i",
1690  [FF_VK_REP_UINT] = "r32ui",
1691  };
1692  return rep_tab[rep_fmt];
1693  };
1694  case AV_PIX_FMT_NV12:
1695  case AV_PIX_FMT_NV16:
1696  case AV_PIX_FMT_NV24: {
1697  const char *rep_tab[] = {
1698  [FF_VK_REP_NATIVE] = "rg8ui",
1699  [FF_VK_REP_FLOAT] = "rg8",
1700  [FF_VK_REP_INT] = "rg8i",
1701  [FF_VK_REP_UINT] = "rg8ui",
1702  };
1703  return rep_tab[rep_fmt];
1704  };
1705  case AV_PIX_FMT_P010:
1706  case AV_PIX_FMT_P210:
1707  case AV_PIX_FMT_P410: {
1708  const char *rep_tab[] = {
1709  [FF_VK_REP_NATIVE] = "rgb10_a2ui",
1710  [FF_VK_REP_FLOAT] = "rgb10_a2",
1711  [FF_VK_REP_INT] = NULL,
1712  [FF_VK_REP_UINT] = "rgb10_a2ui",
1713  };
1714  return rep_tab[rep_fmt];
1715  };
1716  case AV_PIX_FMT_P012:
1717  case AV_PIX_FMT_P016:
1718  case AV_PIX_FMT_P212:
1719  case AV_PIX_FMT_P216:
1720  case AV_PIX_FMT_P412:
1721  case AV_PIX_FMT_P416: {
1722  const char *rep_tab[] = {
1723  [FF_VK_REP_NATIVE] = "rg16ui",
1724  [FF_VK_REP_FLOAT] = "rg16",
1725  [FF_VK_REP_INT] = "rg16i",
1726  [FF_VK_REP_UINT] = "rg16ui",
1727  };
1728  return rep_tab[rep_fmt];
1729  };
1730  default:
1731  return "rgba32f";
1732  }
1733 }
1734 
1735 typedef struct ImageViewCtx {
1737  VkImageView views[];
1738 } ImageViewCtx;
1739 
1740 static void destroy_imageviews(void *opaque, uint8_t *data)
1741 {
1742  FFVulkanContext *s = opaque;
1743  FFVulkanFunctions *vk = &s->vkfn;
1744  ImageViewCtx *iv = (ImageViewCtx *)data;
1745 
1746  for (int i = 0; i < iv->nb_views; i++)
1747  vk->DestroyImageView(s->hwctx->act_dev, iv->views[i], s->hwctx->alloc);
1748 
1749  av_free(iv);
1750 }
1751 
1753 {
1754 #define REPS_FMT(fmt) \
1755  [FF_VK_REP_NATIVE] = fmt ## _UINT, \
1756  [FF_VK_REP_FLOAT] = fmt ## _UNORM, \
1757  [FF_VK_REP_INT] = fmt ## _SINT, \
1758  [FF_VK_REP_UINT] = fmt ## _UINT,
1759 
1760 #define REPS_FMT_PACK(fmt, num) \
1761  [FF_VK_REP_NATIVE] = fmt ## _UINT_PACK ## num, \
1762  [FF_VK_REP_FLOAT] = fmt ## _UNORM_PACK ## num, \
1763  [FF_VK_REP_INT] = fmt ## _SINT_PACK ## num, \
1764  [FF_VK_REP_UINT] = fmt ## _UINT_PACK ## num,
1765 
1766  const VkFormat fmts_map[][4] = {
1767  { REPS_FMT_PACK(VK_FORMAT_A2B10G10R10, 32) },
1768  { REPS_FMT_PACK(VK_FORMAT_A2R10G10B10, 32) },
1769  {
1770  VK_FORMAT_B5G6R5_UNORM_PACK16,
1771  VK_FORMAT_B5G6R5_UNORM_PACK16,
1772  VK_FORMAT_UNDEFINED,
1773  VK_FORMAT_UNDEFINED,
1774  },
1775  {
1776  VK_FORMAT_R5G6B5_UNORM_PACK16,
1777  VK_FORMAT_R5G6B5_UNORM_PACK16,
1778  VK_FORMAT_UNDEFINED,
1779  VK_FORMAT_UNDEFINED,
1780  },
1781  { REPS_FMT(VK_FORMAT_B8G8R8) },
1782  { REPS_FMT(VK_FORMAT_B8G8R8A8) },
1783  { REPS_FMT(VK_FORMAT_R8) },
1784  { REPS_FMT(VK_FORMAT_R8G8) },
1785  { REPS_FMT(VK_FORMAT_R8G8B8) },
1786  { REPS_FMT(VK_FORMAT_R8G8B8A8) },
1787  { REPS_FMT(VK_FORMAT_R16) },
1788  { REPS_FMT(VK_FORMAT_R16G16) },
1789  { REPS_FMT(VK_FORMAT_R16G16B16) },
1790  { REPS_FMT(VK_FORMAT_R16G16B16A16) },
1791  {
1792  VK_FORMAT_R32_UINT,
1793  VK_FORMAT_R32_SFLOAT,
1794  VK_FORMAT_R32_SINT,
1795  VK_FORMAT_R32_UINT,
1796  },
1797  {
1798  VK_FORMAT_R32G32B32_SFLOAT,
1799  VK_FORMAT_R32G32B32_SFLOAT,
1800  VK_FORMAT_UNDEFINED,
1801  VK_FORMAT_UNDEFINED,
1802  },
1803  {
1804  VK_FORMAT_R32G32B32A32_SFLOAT,
1805  VK_FORMAT_R32G32B32A32_SFLOAT,
1806  VK_FORMAT_UNDEFINED,
1807  VK_FORMAT_UNDEFINED,
1808  },
1809  {
1810  VK_FORMAT_R32G32B32_UINT,
1811  VK_FORMAT_UNDEFINED,
1812  VK_FORMAT_R32G32B32_SINT,
1813  VK_FORMAT_R32G32B32_UINT,
1814  },
1815  {
1816  VK_FORMAT_R32G32B32A32_UINT,
1817  VK_FORMAT_UNDEFINED,
1818  VK_FORMAT_R32G32B32A32_SINT,
1819  VK_FORMAT_R32G32B32A32_UINT,
1820  },
1821  };
1822 #undef REPS_FMT_PACK
1823 #undef REPS_FMT
1824 
1825  if (fmt == VK_FORMAT_UNDEFINED)
1826  return VK_FORMAT_UNDEFINED;
1827 
1828  for (int i = 0; i < FF_ARRAY_ELEMS(fmts_map); i++) {
1829  if (fmts_map[i][FF_VK_REP_NATIVE] == fmt ||
1830  fmts_map[i][FF_VK_REP_FLOAT] == fmt ||
1831  fmts_map[i][FF_VK_REP_INT] == fmt ||
1832  fmts_map[i][FF_VK_REP_UINT] == fmt)
1833  return fmts_map[i][rep_fmt];
1834  }
1835 
1836  return VK_FORMAT_UNDEFINED;
1837 }
1838 
1840  VkImageView *img_view, VkImageAspectFlags *aspect,
1841  AVFrame *f, int plane, enum FFVkShaderRepFormat rep_fmt)
1842 {
1843  VkResult ret;
1844  FFVulkanFunctions *vk = &s->vkfn;
1845  AVHWFramesContext *hwfc = (AVHWFramesContext *)f->hw_frames_ctx->data;
1846  AVVulkanFramesContext *vkfc = hwfc->hwctx;
1847  const VkFormat *rep_fmts = av_vkfmt_from_pixfmt(hwfc->sw_format);
1848  AVVkFrame *vkf = (AVVkFrame *)f->data[0];
1849  const int nb_images = ff_vk_count_images(vkf);
1850 
1851  VkImageViewUsageCreateInfo view_usage_info = {
1852  .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO,
1853  .usage = vkfc->usage &
1854  (~(VK_IMAGE_USAGE_VIDEO_ENCODE_SRC_BIT_KHR |
1855  VK_IMAGE_USAGE_VIDEO_DECODE_DST_BIT_KHR)),
1856  };
1857  VkImageViewCreateInfo view_create_info = {
1858  .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
1859  .pNext = &view_usage_info,
1860  .image = vkf->img[FFMIN(plane, nb_images - 1)],
1861  .viewType = VK_IMAGE_VIEW_TYPE_2D,
1862  .format = map_fmt_to_rep(rep_fmts[plane], rep_fmt),
1863  .components = ff_comp_identity_map,
1864  .subresourceRange = {
1865  .aspectMask = ff_vk_aspect_flag(f, plane),
1866  .levelCount = 1,
1867  .layerCount = 1,
1868  },
1869  };
1870  if (view_create_info.format == VK_FORMAT_UNDEFINED) {
1871  av_log(s, AV_LOG_ERROR, "Unable to find a compatible representation "
1872  "of format %i and mode %i\n",
1873  rep_fmts[plane], rep_fmt);
1874  return AVERROR(EINVAL);
1875  }
1876 
1877  ret = vk->CreateImageView(s->hwctx->act_dev, &view_create_info,
1878  s->hwctx->alloc, img_view);
1879  if (ret != VK_SUCCESS) {
1880  av_log(s, AV_LOG_ERROR, "Failed to create imageview: %s\n",
1881  ff_vk_ret2str(ret));
1882  return AVERROR_EXTERNAL;
1883  }
1884 
1885  *aspect = view_create_info.subresourceRange.aspectMask;
1886 
1887  return 0;
1888 }
1889 
1891  VkImageView views[AV_NUM_DATA_POINTERS],
1892  AVFrame *f, enum FFVkShaderRepFormat rep_fmt)
1893 {
1894  int err;
1895  VkResult ret;
1896  AVBufferRef *buf;
1897  FFVulkanFunctions *vk = &s->vkfn;
1898  AVHWFramesContext *hwfc = (AVHWFramesContext *)f->hw_frames_ctx->data;
1899  AVVulkanFramesContext *vkfc = hwfc->hwctx;
1900  const VkFormat *rep_fmts = av_vkfmt_from_pixfmt(hwfc->sw_format);
1901  AVVkFrame *vkf = (AVVkFrame *)f->data[0];
1902  const int nb_images = ff_vk_count_images(vkf);
1903  const int nb_planes = av_pix_fmt_count_planes(hwfc->sw_format);
1904 
1905  ImageViewCtx *iv;
1906  const size_t buf_size = sizeof(*iv) + nb_planes*sizeof(VkImageView);
1907  iv = av_mallocz(buf_size);
1908  if (!iv)
1909  return AVERROR(ENOMEM);
1910 
1911  for (int i = 0; i < nb_planes; i++) {
1912  VkImageViewUsageCreateInfo view_usage_info = {
1913  .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO,
1914  .usage = vkfc->usage &
1915  (~(VK_IMAGE_USAGE_VIDEO_ENCODE_SRC_BIT_KHR |
1916  VK_IMAGE_USAGE_VIDEO_DECODE_DST_BIT_KHR)),
1917  };
1918  VkImageViewCreateInfo view_create_info = {
1919  .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
1920  .pNext = &view_usage_info,
1921  .image = vkf->img[FFMIN(i, nb_images - 1)],
1922  .viewType = VK_IMAGE_VIEW_TYPE_2D,
1923  .format = map_fmt_to_rep(rep_fmts[i], rep_fmt),
1924  .components = ff_comp_identity_map,
1925  .subresourceRange = {
1926  .aspectMask = ff_vk_aspect_flag(f, i),
1927  .levelCount = 1,
1928  .layerCount = 1,
1929  },
1930  };
1931  if (view_create_info.format == VK_FORMAT_UNDEFINED) {
1932  av_log(s, AV_LOG_ERROR, "Unable to find a compatible representation "
1933  "of format %i and mode %i\n",
1934  rep_fmts[i], rep_fmt);
1935  err = AVERROR(EINVAL);
1936  goto fail;
1937  }
1938 
1939  ret = vk->CreateImageView(s->hwctx->act_dev, &view_create_info,
1940  s->hwctx->alloc, &iv->views[i]);
1941  if (ret != VK_SUCCESS) {
1942  av_log(s, AV_LOG_ERROR, "Failed to create imageview: %s\n",
1943  ff_vk_ret2str(ret));
1944  err = AVERROR_EXTERNAL;
1945  goto fail;
1946  }
1947 
1948  iv->nb_views++;
1949  }
1950 
1951  buf = av_buffer_create((uint8_t *)iv, buf_size, destroy_imageviews, s, 0);
1952  if (!buf) {
1953  err = AVERROR(ENOMEM);
1954  goto fail;
1955  }
1956 
1957  /* Add to queue dependencies */
1958  err = ff_vk_exec_add_dep_buf(s, e, &buf, 1, 0);
1959  if (err < 0)
1960  av_buffer_unref(&buf);
1961 
1962  memcpy(views, iv->views, nb_planes*sizeof(*views));
1963 
1964  return err;
1965 
1966 fail:
1967  for (int i = 0; i < iv->nb_views; i++)
1968  vk->DestroyImageView(s->hwctx->act_dev, iv->views[i], s->hwctx->alloc);
1969  av_free(iv);
1970  return err;
1971 }
1972 
1974  AVFrame *pic, VkImageMemoryBarrier2 *bar, int *nb_bar,
1975  VkPipelineStageFlags src_stage,
1976  VkPipelineStageFlags dst_stage,
1977  VkAccessFlagBits new_access,
1978  VkImageLayout new_layout,
1979  uint32_t new_qf)
1980 {
1981  int found = -1;
1982  AVVkFrame *vkf = (AVVkFrame *)pic->data[0];
1983  const int nb_images = ff_vk_count_images(vkf);
1984  for (int i = 0; i < e->nb_frame_deps; i++)
1985  if (e->frame_deps[i]->data[0] == pic->data[0]) {
1986  if (e->frame_update[i])
1987  found = i;
1988  break;
1989  }
1990 
1991  for (int i = 0; i < nb_images; i++) {
1992  bar[*nb_bar] = (VkImageMemoryBarrier2) {
1993  .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2,
1994  .pNext = NULL,
1995  .srcStageMask = src_stage,
1996  .dstStageMask = dst_stage,
1997  .srcAccessMask = found >= 0 ? e->access_dst[found] : vkf->access[i],
1998  .dstAccessMask = new_access,
1999  .oldLayout = found >= 0 ? e->layout_dst[found] : vkf->layout[0],
2000  .newLayout = new_layout,
2001  .srcQueueFamilyIndex = found >= 0 ? e->queue_family_dst[found] : vkf->queue_family[0],
2002  .dstQueueFamilyIndex = new_qf,
2003  .image = vkf->img[i],
2004  .subresourceRange = (VkImageSubresourceRange) {
2005  .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
2006  .layerCount = 1,
2007  .levelCount = 1,
2008  },
2009  };
2010  *nb_bar += 1;
2011  }
2012 
2013  ff_vk_exec_update_frame(s, e, pic, &bar[*nb_bar - nb_images], NULL);
2014 }
2015 
2017  VkPipelineStageFlags stage,
2018  const char *extensions[], int nb_extensions,
2019  int lg_x, int lg_y, int lg_z,
2020  uint32_t required_subgroup_size)
2021 {
2023 
2024  shd->name = name;
2025  shd->stage = stage;
2026  shd->lg_size[0] = lg_x;
2027  shd->lg_size[1] = lg_y;
2028  shd->lg_size[2] = lg_z;
2029 
2030  switch (shd->stage) {
2031  case VK_SHADER_STAGE_ANY_HIT_BIT_KHR:
2032  case VK_SHADER_STAGE_CALLABLE_BIT_KHR:
2033  case VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR:
2034  case VK_SHADER_STAGE_INTERSECTION_BIT_KHR:
2035  case VK_SHADER_STAGE_MISS_BIT_KHR:
2036  case VK_SHADER_STAGE_RAYGEN_BIT_KHR:
2037  shd->bind_point = VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR;
2038  break;
2039  case VK_SHADER_STAGE_COMPUTE_BIT:
2040  shd->bind_point = VK_PIPELINE_BIND_POINT_COMPUTE;
2041  break;
2042  default:
2043  shd->bind_point = VK_PIPELINE_BIND_POINT_GRAPHICS;
2044  break;
2045  };
2046 
2047  if (required_subgroup_size) {
2048  shd->subgroup_info.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_REQUIRED_SUBGROUP_SIZE_CREATE_INFO;
2049  shd->subgroup_info.requiredSubgroupSize = required_subgroup_size;
2050  }
2051 
2052  av_bprintf(&shd->src, "/* %s shader: %s */\n",
2053  (stage == VK_SHADER_STAGE_TASK_BIT_EXT ||
2054  stage == VK_SHADER_STAGE_MESH_BIT_EXT) ?
2055  "Mesh" :
2056  (shd->bind_point == VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR) ?
2057  "Raytrace" :
2058  (shd->bind_point == VK_PIPELINE_BIND_POINT_COMPUTE) ?
2059  "Compute" : "Graphics",
2060  name);
2061  GLSLF(0, #version %i ,460);
2062  GLSLC(0, );
2063 
2064  /* Common utilities */
2065  GLSLC(0, #define IS_WITHIN(v1, v2) ((v1.x < v2.x) && (v1.y < v2.y)) );
2066  GLSLC(0, );
2067  GLSLC(0, #extension GL_EXT_scalar_block_layout : require );
2068  GLSLC(0, #extension GL_EXT_shader_explicit_arithmetic_types : require );
2069  GLSLC(0, #extension GL_EXT_control_flow_attributes : require );
2070  GLSLC(0, #extension GL_EXT_shader_image_load_formatted : require );
2071  if (s->extensions & FF_VK_EXT_EXPECT_ASSUME) {
2072  GLSLC(0, #extension GL_EXT_expect_assume : require );
2073  } else {
2074  GLSLC(0, #define assumeEXT(x) (x) );
2075  GLSLC(0, #define expectEXT(x, c) (x) );
2076  }
2077  if ((s->extensions & FF_VK_EXT_DEBUG_UTILS) &&
2078  (s->extensions & FF_VK_EXT_RELAXED_EXTENDED_INSTR)) {
2079  GLSLC(0, #extension GL_EXT_debug_printf : require );
2080  GLSLC(0, #define DEBUG );
2081  }
2082 
2083  if (stage == VK_SHADER_STAGE_TASK_BIT_EXT ||
2084  stage == VK_SHADER_STAGE_MESH_BIT_EXT)
2085  GLSLC(0, #extension GL_EXT_mesh_shader : require );
2086 
2087  for (int i = 0; i < nb_extensions; i++)
2088  GLSLF(0, #extension %s : %s ,extensions[i], "require");
2089  GLSLC(0, );
2090 
2091  GLSLF(0, layout (local_size_x = %i, local_size_y = %i, local_size_z = %i) in;
2092  , shd->lg_size[0], shd->lg_size[1], shd->lg_size[2]);
2093  GLSLC(0, );
2094 
2095  return 0;
2096 }
2097 
2098 void ff_vk_shader_print(void *ctx, FFVulkanShader *shd, int prio)
2099 {
2100  int line = 0;
2101  const char *p = shd->src.str;
2102  const char *start = p;
2103  const size_t len = strlen(p);
2104 
2105  AVBPrint buf;
2107 
2108  for (int i = 0; i < len; i++) {
2109  if (p[i] == '\n') {
2110  av_bprintf(&buf, "%i\t", ++line);
2111  av_bprint_append_data(&buf, start, &p[i] - start + 1);
2112  start = &p[i + 1];
2113  }
2114  }
2115 
2116  av_log(ctx, prio, "Shader %s: \n%s", shd->name, buf.str);
2117  av_bprint_finalize(&buf, NULL);
2118 }
2119 
2121 {
2122  VkResult ret;
2123  FFVulkanFunctions *vk = &s->vkfn;
2124  VkPipelineLayoutCreateInfo pipeline_layout_info;
2125 
2126  /* Finally create the pipeline layout */
2127  pipeline_layout_info = (VkPipelineLayoutCreateInfo) {
2128  .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
2129  .pSetLayouts = shd->desc_layout,
2130  .setLayoutCount = shd->nb_descriptor_sets,
2131  .pushConstantRangeCount = shd->push_consts_num,
2132  .pPushConstantRanges = shd->push_consts,
2133  };
2134 
2135  ret = vk->CreatePipelineLayout(s->hwctx->act_dev, &pipeline_layout_info,
2136  s->hwctx->alloc, &shd->pipeline_layout);
2137  if (ret != VK_SUCCESS) {
2138  av_log(s, AV_LOG_ERROR, "Unable to init pipeline layout: %s\n",
2139  ff_vk_ret2str(ret));
2140  return AVERROR_EXTERNAL;
2141  }
2142 
2143  return 0;
2144 }
2145 
2147  VkShaderModule *mod,
2148  uint8_t *spirv, size_t spirv_len)
2149 {
2150  VkResult ret;
2151  FFVulkanFunctions *vk = &s->vkfn;
2152 
2153  VkShaderModuleCreateInfo shader_module_info = {
2154  .sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO,
2155  .pNext = NULL,
2156  .flags = 0x0,
2157  .pCode = (void *)spirv,
2158  .codeSize = spirv_len,
2159  };
2160 
2161  ret = vk->CreateShaderModule(s->hwctx->act_dev, &shader_module_info,
2162  s->hwctx->alloc, mod);
2163  if (ret != VK_SUCCESS) {
2164  av_log(s, AV_LOG_ERROR, "Error creating shader module: %s\n",
2165  ff_vk_ret2str(ret));
2166  return AVERROR_EXTERNAL;
2167  }
2168 
2169  return 0;
2170 }
2171 
2173  VkShaderModule mod, const char *entrypoint)
2174 {
2175  VkResult ret;
2176  FFVulkanFunctions *vk = &s->vkfn;
2177 
2178  VkComputePipelineCreateInfo pipeline_create_info = {
2179  .sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,
2180  .flags = (s->extensions & FF_VK_EXT_DESCRIPTOR_BUFFER) ?
2181  VK_PIPELINE_CREATE_DESCRIPTOR_BUFFER_BIT_EXT : 0x0,
2182  .layout = shd->pipeline_layout,
2183  .stage = (VkPipelineShaderStageCreateInfo) {
2184  .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
2185  .pNext = shd->subgroup_info.requiredSubgroupSize ?
2186  &shd->subgroup_info : NULL,
2187  .pName = entrypoint,
2188  .flags = shd->subgroup_info.requiredSubgroupSize ?
2189  VK_PIPELINE_SHADER_STAGE_CREATE_REQUIRE_FULL_SUBGROUPS_BIT : 0x0,
2190  .stage = shd->stage,
2191  .module = mod,
2192  },
2193  };
2194 
2195  ret = vk->CreateComputePipelines(s->hwctx->act_dev, VK_NULL_HANDLE, 1,
2196  &pipeline_create_info,
2197  s->hwctx->alloc, &shd->pipeline);
2198  if (ret != VK_SUCCESS) {
2199  av_log(s, AV_LOG_ERROR, "Unable to init compute pipeline: %s\n",
2200  ff_vk_ret2str(ret));
2201  return AVERROR_EXTERNAL;
2202  }
2203 
2204  return 0;
2205 }
2206 
2208  uint8_t *spirv, size_t spirv_len,
2209  const char *entrypoint)
2210 {
2211  VkResult ret;
2212  FFVulkanFunctions *vk = &s->vkfn;
2213  size_t shader_size = 0;
2214 
2215  VkShaderCreateInfoEXT shader_obj_create = {
2216  .sType = VK_STRUCTURE_TYPE_SHADER_CREATE_INFO_EXT,
2217  .flags = shd->subgroup_info.requiredSubgroupSize ?
2218  VK_SHADER_CREATE_REQUIRE_FULL_SUBGROUPS_BIT_EXT : 0x0,
2219  .stage = shd->stage,
2220  .nextStage = 0,
2221  .codeType = VK_SHADER_CODE_TYPE_SPIRV_EXT,
2222  .pCode = spirv,
2223  .codeSize = spirv_len,
2224  .pName = entrypoint,
2225  .pSetLayouts = shd->desc_layout,
2226  .setLayoutCount = shd->nb_descriptor_sets,
2227  .pushConstantRangeCount = shd->push_consts_num,
2228  .pPushConstantRanges = shd->push_consts,
2229  .pSpecializationInfo = NULL,
2230  };
2231 
2232  ret = vk->CreateShadersEXT(s->hwctx->act_dev, 1, &shader_obj_create,
2233  s->hwctx->alloc, &shd->object);
2234  if (ret != VK_SUCCESS) {
2235  av_log(s, AV_LOG_ERROR, "Unable to create shader object: %s\n",
2236  ff_vk_ret2str(ret));
2237  return AVERROR_EXTERNAL;
2238  }
2239 
2240  if (vk->GetShaderBinaryDataEXT(s->hwctx->act_dev, shd->object,
2241  &shader_size, NULL) == VK_SUCCESS)
2242  av_log(s, AV_LOG_VERBOSE, "Shader %s size: %zu binary (%zu SPIR-V)\n",
2243  shd->name, shader_size, spirv_len);
2244 
2245  return 0;
2246 }
2247 
2249 {
2250  VkResult ret;
2251  FFVulkanFunctions *vk = &s->vkfn;
2252 
2254  sizeof(*shd->desc_layout));
2255  if (!shd->desc_layout)
2256  return AVERROR(ENOMEM);
2257 
2258  if (!(s->extensions & FF_VK_EXT_DESCRIPTOR_BUFFER)) {
2259  int has_singular = 0;
2260  int max_descriptors = 0;
2261  for (int i = 0; i < shd->nb_descriptor_sets; i++) {
2262  max_descriptors = FFMAX(max_descriptors, shd->desc_set[i].nb_bindings);
2263  if (shd->desc_set[i].singular)
2264  has_singular = 1;
2265  }
2266  shd->use_push = (s->extensions & FF_VK_EXT_PUSH_DESCRIPTOR) &&
2267  (max_descriptors <= s->push_desc_props.maxPushDescriptors) &&
2268  (shd->nb_descriptor_sets == 1) &&
2269  (has_singular == 0);
2270  }
2271 
2272  for (int i = 0; i < shd->nb_descriptor_sets; i++) {
2273  FFVulkanDescriptorSet *set = &shd->desc_set[i];
2274  VkDescriptorSetLayoutCreateInfo desc_layout_create = {
2275  .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
2276  .bindingCount = set->nb_bindings,
2277  .pBindings = set->binding,
2278  .flags = (s->extensions & FF_VK_EXT_DESCRIPTOR_BUFFER) ?
2279  VK_DESCRIPTOR_SET_LAYOUT_CREATE_DESCRIPTOR_BUFFER_BIT_EXT :
2280  (shd->use_push) ?
2281  VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR :
2282  0x0,
2283  };
2284 
2285  ret = vk->CreateDescriptorSetLayout(s->hwctx->act_dev,
2286  &desc_layout_create,
2287  s->hwctx->alloc,
2288  &shd->desc_layout[i]);
2289  if (ret != VK_SUCCESS) {
2290  av_log(s, AV_LOG_ERROR, "Unable to create descriptor set layout: %s",
2291  ff_vk_ret2str(ret));
2292  return AVERROR_EXTERNAL;
2293  }
2294 
2295  if (s->extensions & FF_VK_EXT_DESCRIPTOR_BUFFER) {
2296  vk->GetDescriptorSetLayoutSizeEXT(s->hwctx->act_dev, shd->desc_layout[i],
2297  &set->layout_size);
2298 
2299  set->aligned_size = FFALIGN(set->layout_size,
2300  s->desc_buf_props.descriptorBufferOffsetAlignment);
2301 
2302  for (int j = 0; j < set->nb_bindings; j++)
2303  vk->GetDescriptorSetLayoutBindingOffsetEXT(s->hwctx->act_dev,
2304  shd->desc_layout[i],
2305  j,
2306  &set->binding_offset[j]);
2307  }
2308  }
2309 
2310  return 0;
2311 }
2312 
2314  uint8_t *spirv, size_t spirv_len,
2315  const char *entrypoint)
2316 {
2317  int err;
2318  FFVulkanFunctions *vk = &s->vkfn;
2319 
2320  err = init_descriptors(s, shd);
2321  if (err < 0)
2322  return err;
2323 
2324  err = init_pipeline_layout(s, shd);
2325  if (err < 0)
2326  return err;
2327 
2328  if (s->extensions & FF_VK_EXT_DESCRIPTOR_BUFFER) {
2330  sizeof(*shd->bound_buffer_indices));
2331  if (!shd->bound_buffer_indices)
2332  return AVERROR(ENOMEM);
2333 
2334  for (int i = 0; i < shd->nb_descriptor_sets; i++)
2335  shd->bound_buffer_indices[i] = i;
2336  }
2337 
2338  if (s->extensions & FF_VK_EXT_SHADER_OBJECT) {
2339  err = create_shader_object(s, shd, spirv, spirv_len, entrypoint);
2340  if (err < 0)
2341  return err;
2342  } else {
2343  VkShaderModule mod;
2344  err = create_shader_module(s, shd, &mod, spirv, spirv_len);
2345  if (err < 0)
2346  return err;
2347 
2348  switch (shd->bind_point) {
2349  case VK_PIPELINE_BIND_POINT_COMPUTE:
2350  err = init_compute_pipeline(s, shd, mod, entrypoint);
2351  break;
2352  default:
2353  av_log(s, AV_LOG_ERROR, "Unsupported shader type: %i\n",
2354  shd->bind_point);
2355  err = AVERROR(EINVAL);
2356  break;
2357  };
2358 
2359  vk->DestroyShaderModule(s->hwctx->act_dev, mod, s->hwctx->alloc);
2360  if (err < 0)
2361  return err;
2362  }
2363 
2364  return 0;
2365 }
2366 
2367 static const struct descriptor_props {
2368  size_t struct_size; /* Size of the opaque which updates the descriptor */
2369  const char *type;
2371  int mem_quali; /* Can use a memory qualifier */
2372  int dim_needed; /* Must indicate dimension */
2373  int buf_content; /* Must indicate buffer contents */
2374 } descriptor_props[] = {
2375  [VK_DESCRIPTOR_TYPE_SAMPLER] = { sizeof(VkDescriptorImageInfo), "sampler", 1, 0, 0, 0, },
2376  [VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE] = { sizeof(VkDescriptorImageInfo), "texture", 1, 0, 1, 0, },
2377  [VK_DESCRIPTOR_TYPE_STORAGE_IMAGE] = { sizeof(VkDescriptorImageInfo), "image", 1, 1, 1, 0, },
2378  [VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT] = { sizeof(VkDescriptorImageInfo), "subpassInput", 1, 0, 0, 0, },
2379  [VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER] = { sizeof(VkDescriptorImageInfo), "sampler", 1, 0, 1, 0, },
2380  [VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER] = { sizeof(VkDescriptorBufferInfo), NULL, 1, 0, 0, 1, },
2381  [VK_DESCRIPTOR_TYPE_STORAGE_BUFFER] = { sizeof(VkDescriptorBufferInfo), "buffer", 0, 1, 0, 1, },
2382  [VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC] = { sizeof(VkDescriptorBufferInfo), NULL, 1, 0, 0, 1, },
2383  [VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC] = { sizeof(VkDescriptorBufferInfo), "buffer", 0, 1, 0, 1, },
2384  [VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER] = { sizeof(VkBufferView), "samplerBuffer", 1, 0, 0, 0, },
2385  [VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER] = { sizeof(VkBufferView), "imageBuffer", 1, 0, 0, 0, },
2386 };
2387 
2390  int singular, int print_to_shader_only)
2391 {
2392  int has_sampler = 0;
2394 
2395  if (print_to_shader_only)
2396  goto print;
2397 
2398  /* Actual layout allocated for the pipeline */
2399  set = av_realloc_array(shd->desc_set,
2400  sizeof(*shd->desc_set),
2401  shd->nb_descriptor_sets + 1);
2402  if (!set)
2403  return AVERROR(ENOMEM);
2404  shd->desc_set = set;
2405 
2406  set = &set[shd->nb_descriptor_sets];
2407  memset(set, 0, sizeof(*set));
2408 
2409  set->binding = av_calloc(nb, sizeof(*set->binding));
2410  if (!set->binding)
2411  return AVERROR(ENOMEM);
2412 
2413  set->binding_offset = av_calloc(nb, sizeof(*set->binding_offset));
2414  if (!set->binding_offset) {
2415  av_freep(&set->binding);
2416  return AVERROR(ENOMEM);
2417  }
2418 
2419  for (int i = 0; i < nb; i++) {
2420  set->binding[i].binding = i;
2421  set->binding[i].descriptorType = desc[i].type;
2422  set->binding[i].descriptorCount = FFMAX(desc[i].elems, 1);
2423  set->binding[i].stageFlags = desc[i].stages;
2424  set->binding[i].pImmutableSamplers = desc[i].samplers;
2425 
2426  if (desc[i].type == VK_DESCRIPTOR_TYPE_SAMPLER ||
2427  desc[i].type == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
2428  has_sampler |= 1;
2429  }
2430 
2431  set->usage = VK_BUFFER_USAGE_RESOURCE_DESCRIPTOR_BUFFER_BIT_EXT |
2432  VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT;
2433  if (has_sampler)
2434  set->usage |= VK_BUFFER_USAGE_SAMPLER_DESCRIPTOR_BUFFER_BIT_EXT;
2435 
2436  if (!(s->extensions & FF_VK_EXT_DESCRIPTOR_BUFFER)) {
2437  for (int i = 0; i < nb; i++) {
2438  int j;
2439  VkDescriptorPoolSize *desc_pool_size;
2440  for (j = 0; j < shd->nb_desc_pool_size; j++)
2441  if (shd->desc_pool_size[j].type == desc[i].type)
2442  break;
2443  if (j >= shd->nb_desc_pool_size) {
2444  desc_pool_size = av_realloc_array(shd->desc_pool_size,
2445  sizeof(*desc_pool_size),
2446  shd->nb_desc_pool_size + 1);
2447  if (!desc_pool_size)
2448  return AVERROR(ENOMEM);
2449 
2450  shd->desc_pool_size = desc_pool_size;
2451  shd->nb_desc_pool_size++;
2452  memset(&desc_pool_size[j], 0, sizeof(VkDescriptorPoolSize));
2453  }
2454  shd->desc_pool_size[j].type = desc[i].type;
2455  shd->desc_pool_size[j].descriptorCount += FFMAX(desc[i].elems, 1);
2456  }
2457  }
2458 
2459  set->singular = singular;
2460  set->nb_bindings = nb;
2461  shd->nb_descriptor_sets++;
2462 
2463 print:
2464  /* Write shader info */
2465  for (int i = 0; i < nb; i++) {
2466  const struct descriptor_props *prop = &descriptor_props[desc[i].type];
2467  GLSLA("layout (set = %i, binding = %i", FFMAX(shd->nb_descriptor_sets - 1, 0), i);
2468 
2469  if (desc[i].mem_layout &&
2470  (desc[i].type != VK_DESCRIPTOR_TYPE_STORAGE_IMAGE))
2471  GLSLA(", %s", desc[i].mem_layout);
2472 
2473  GLSLA(")");
2474 
2475  if (prop->is_uniform)
2476  GLSLA(" uniform");
2477 
2478  if (prop->mem_quali && desc[i].mem_quali)
2479  GLSLA(" %s", desc[i].mem_quali);
2480 
2481  if (prop->type) {
2482  GLSLA(" ");
2483  if (desc[i].type == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE) {
2484  if (desc[i].mem_layout) {
2485  int len = strlen(desc[i].mem_layout);
2486  if (desc[i].mem_layout[len - 1] == 'i' &&
2487  desc[i].mem_layout[len - 2] == 'u') {
2488  GLSLA("u");
2489  } else if (desc[i].mem_layout[len - 1] == 'i') {
2490  GLSLA("i");
2491  }
2492  }
2493  }
2494  GLSLA("%s", prop->type);
2495  }
2496 
2497  if (prop->dim_needed)
2498  GLSLA("%iD", desc[i].dimensions);
2499 
2500  GLSLA(" %s", desc[i].name);
2501 
2502  if (prop->buf_content) {
2503  GLSLA(" {\n ");
2504  if (desc[i].buf_elems) {
2505  GLSLA("%s", desc[i].buf_content);
2506  GLSLA("[%i];", desc[i].buf_elems);
2507  } else {
2508  GLSLA("%s", desc[i].buf_content);
2509  }
2510  GLSLA("\n}");
2511  } else if (desc[i].elems > 0) {
2512  GLSLA("[%i]", desc[i].elems);
2513  }
2514 
2515  GLSLA(";");
2516  GLSLA("\n");
2517  }
2518  GLSLA("\n");
2519 
2520  return 0;
2521 }
2522 
2524  FFVulkanShader *shd)
2525 {
2526  int err;
2527  FFVulkanShaderData *sd;
2528 
2529  if (!shd->nb_descriptor_sets)
2530  return 0;
2531 
2532  sd = av_realloc_array(pool->reg_shd,
2533  sizeof(*pool->reg_shd),
2534  pool->nb_reg_shd + 1);
2535  if (!sd)
2536  return AVERROR(ENOMEM);
2537 
2538  pool->reg_shd = sd;
2539  sd = &sd[pool->nb_reg_shd++];
2540  memset(sd, 0, sizeof(*sd));
2541 
2542  sd->shd = shd;
2544 
2545  if (s->extensions & FF_VK_EXT_DESCRIPTOR_BUFFER) {
2546  sd->desc_bind = av_malloc_array(sd->nb_descriptor_sets, sizeof(*sd->desc_bind));
2547  if (!sd->desc_bind)
2548  return AVERROR(ENOMEM);
2549 
2550  sd->desc_set_buf = av_calloc(sd->nb_descriptor_sets, sizeof(*sd->desc_set_buf));
2551  if (!sd->desc_set_buf)
2552  return AVERROR(ENOMEM);
2553 
2554  for (int i = 0; i < sd->nb_descriptor_sets; i++) {
2555  FFVulkanDescriptorSet *set = &shd->desc_set[i];
2557  int nb = set->singular ? 1 : pool->pool_size;
2558 
2559  err = ff_vk_create_buf(s, &sdb->buf,
2560  set->aligned_size*nb,
2561  NULL, NULL, set->usage,
2562  VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT |
2563  VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
2564  VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
2565  if (err < 0)
2566  return err;
2567 
2568  err = ff_vk_map_buffer(s, &sdb->buf, &sdb->desc_mem, 0);
2569  if (err < 0)
2570  return err;
2571 
2572  sd->desc_bind[i] = (VkDescriptorBufferBindingInfoEXT) {
2573  .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_BUFFER_BINDING_INFO_EXT,
2574  .usage = set->usage,
2575  .address = sdb->buf.address,
2576  };
2577  }
2578  } else if (!shd->use_push) {
2579  VkResult ret;
2580  FFVulkanFunctions *vk = &s->vkfn;
2581  VkDescriptorSetLayout *tmp_layouts;
2582  VkDescriptorSetAllocateInfo set_alloc_info;
2583  VkDescriptorPoolCreateInfo pool_create_info;
2584 
2585  for (int i = 0; i < shd->nb_desc_pool_size; i++)
2586  shd->desc_pool_size[i].descriptorCount *= pool->pool_size;
2587 
2588  pool_create_info = (VkDescriptorPoolCreateInfo) {
2589  .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
2590  .flags = 0,
2591  .pPoolSizes = shd->desc_pool_size,
2592  .poolSizeCount = shd->nb_desc_pool_size,
2593  .maxSets = sd->nb_descriptor_sets*pool->pool_size,
2594  };
2595 
2596  ret = vk->CreateDescriptorPool(s->hwctx->act_dev, &pool_create_info,
2597  s->hwctx->alloc, &sd->desc_pool);
2598  if (ret != VK_SUCCESS) {
2599  av_log(s, AV_LOG_ERROR, "Unable to create descriptor pool: %s\n",
2600  ff_vk_ret2str(ret));
2601  return AVERROR_EXTERNAL;
2602  }
2603 
2604  tmp_layouts = av_malloc_array(pool_create_info.maxSets, sizeof(*tmp_layouts));
2605  if (!tmp_layouts)
2606  return AVERROR(ENOMEM);
2607 
2608  /* Colate each execution context's descriptor set layouts */
2609  for (int i = 0; i < pool->pool_size; i++)
2610  for (int j = 0; j < sd->nb_descriptor_sets; j++)
2611  tmp_layouts[i*sd->nb_descriptor_sets + j] = shd->desc_layout[j];
2612 
2613  set_alloc_info = (VkDescriptorSetAllocateInfo) {
2614  .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
2615  .descriptorPool = sd->desc_pool,
2616  .pSetLayouts = tmp_layouts,
2617  .descriptorSetCount = pool_create_info.maxSets,
2618  };
2619 
2620  sd->desc_sets = av_malloc_array(pool_create_info.maxSets,
2621  sizeof(*tmp_layouts));
2622  if (!sd->desc_sets) {
2623  av_free(tmp_layouts);
2624  return AVERROR(ENOMEM);
2625  }
2626  ret = vk->AllocateDescriptorSets(s->hwctx->act_dev, &set_alloc_info,
2627  sd->desc_sets);
2628  av_free(tmp_layouts);
2629  if (ret != VK_SUCCESS) {
2630  av_log(s, AV_LOG_ERROR, "Unable to allocate descriptor set: %s\n",
2631  ff_vk_ret2str(ret));
2632  av_freep(&sd->desc_sets);
2633  return AVERROR_EXTERNAL;
2634  }
2635  }
2636 
2637  return 0;
2638 }
2639 
2641  FFVulkanShader *shd)
2642 {
2643  for (int i = 0; i < e->parent->nb_reg_shd; i++)
2644  if (e->parent->reg_shd[i].shd == shd)
2645  return &e->parent->reg_shd[i];
2646  return NULL;
2647 }
2648 
2650  FFVulkanShader *shd, int set,
2651  int bind_idx, int array_idx,
2652  VkDescriptorGetInfoEXT *desc_get_info,
2653  size_t desc_size)
2654 {
2655  FFVulkanFunctions *vk = &s->vkfn;
2656  FFVulkanDescriptorSet *desc_set = &shd->desc_set[set];
2657  FFVulkanShaderData *sd = get_shd_data(e, shd);
2658  const size_t exec_offset = desc_set->singular ? 0 : desc_set->aligned_size*e->idx;
2659 
2660  void *desc = sd->desc_set_buf[set].desc_mem + /* Base */
2661  exec_offset + /* Execution context */
2662  desc_set->binding_offset[bind_idx] + /* Descriptor binding */
2663  array_idx*desc_size; /* Array position */
2664 
2665  vk->GetDescriptorEXT(s->hwctx->act_dev, desc_get_info, desc_size, desc);
2666 }
2667 
2669  FFVulkanShader *shd, int set,
2670  VkWriteDescriptorSet *write_info)
2671 {
2672  FFVulkanFunctions *vk = &s->vkfn;
2673  FFVulkanDescriptorSet *desc_set = &shd->desc_set[set];
2674  FFVulkanShaderData *sd = get_shd_data(e, shd);
2675 
2676  if (desc_set->singular) {
2677  for (int i = 0; i < e->parent->pool_size; i++) {
2678  write_info->dstSet = sd->desc_sets[i*sd->nb_descriptor_sets + set];
2679  vk->UpdateDescriptorSets(s->hwctx->act_dev, 1, write_info, 0, NULL);
2680  }
2681  } else {
2682  if (shd->use_push) {
2683  vk->CmdPushDescriptorSetKHR(e->buf,
2684  shd->bind_point,
2685  shd->pipeline_layout,
2686  set, 1,
2687  write_info);
2688  } else {
2689  write_info->dstSet = sd->desc_sets[e->idx*sd->nb_descriptor_sets + set];
2690  vk->UpdateDescriptorSets(s->hwctx->act_dev, 1, write_info, 0, NULL);
2691  }
2692  }
2693 }
2694 
2696  FFVulkanShader *shd, int set, int bind, int offs,
2697  VkImageView view, VkImageLayout layout,
2698  VkSampler sampler)
2699 {
2700  FFVulkanDescriptorSet *desc_set = &shd->desc_set[set];
2701 
2702  if (s->extensions & FF_VK_EXT_DESCRIPTOR_BUFFER) {
2703  VkDescriptorGetInfoEXT desc_get_info = {
2704  .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_GET_INFO_EXT,
2705  .type = desc_set->binding[bind].descriptorType,
2706  };
2707  VkDescriptorImageInfo desc_img_info = {
2708  .imageView = view,
2709  .sampler = sampler,
2710  .imageLayout = layout,
2711  };
2712  size_t desc_size;
2713 
2714  switch (desc_get_info.type) {
2715  case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
2716  desc_get_info.data.pSampledImage = &desc_img_info;
2717  desc_size = s->desc_buf_props.sampledImageDescriptorSize;
2718  break;
2719  case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
2720  desc_get_info.data.pStorageImage = &desc_img_info;
2721  desc_size = s->desc_buf_props.storageImageDescriptorSize;
2722  break;
2723  case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
2724  desc_get_info.data.pInputAttachmentImage = &desc_img_info;
2725  desc_size = s->desc_buf_props.inputAttachmentDescriptorSize;
2726  break;
2727  case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
2728  desc_get_info.data.pCombinedImageSampler = &desc_img_info;
2729  desc_size = s->desc_buf_props.combinedImageSamplerDescriptorSize;
2730  break;
2731  default:
2732  av_log(s, AV_LOG_ERROR, "Invalid descriptor type at set %i binding %i: %i!\n",
2733  set, bind, desc_get_info.type);
2734  return AVERROR(EINVAL);
2735  break;
2736  };
2737 
2738  update_set_descriptor(s, e, shd, set, bind, offs,
2739  &desc_get_info, desc_size);
2740  } else {
2741  VkDescriptorImageInfo desc_pool_write_info_img = {
2742  .sampler = sampler,
2743  .imageView = view,
2744  .imageLayout = layout,
2745  };
2746  VkWriteDescriptorSet desc_pool_write_info = {
2747  .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
2748  .dstBinding = bind,
2749  .descriptorCount = 1,
2750  .dstArrayElement = offs,
2751  .descriptorType = desc_set->binding[bind].descriptorType,
2752  .pImageInfo = &desc_pool_write_info_img,
2753  };
2754  update_set_pool_write(s, e, shd, set, &desc_pool_write_info);
2755  }
2756 
2757  return 0;
2758 }
2759 
2761  FFVulkanShader *shd, AVFrame *f,
2762  VkImageView *views, int set, int binding,
2763  VkImageLayout layout, VkSampler sampler)
2764 {
2765  AVHWFramesContext *hwfc = (AVHWFramesContext *)f->hw_frames_ctx->data;
2766  const int nb_planes = av_pix_fmt_count_planes(hwfc->sw_format);
2767 
2768  for (int i = 0; i < nb_planes; i++)
2769  ff_vk_shader_update_img(s, e, shd, set, binding, i,
2770  views[i], layout, sampler);
2771 }
2772 
2774  FFVulkanShader *shd,
2775  int set, int bind, int elem,
2776  FFVkBuffer *buf, VkDeviceSize offset, VkDeviceSize len,
2777  VkFormat fmt)
2778 {
2779  FFVulkanDescriptorSet *desc_set = &shd->desc_set[set];
2780 
2781  if (s->extensions & FF_VK_EXT_DESCRIPTOR_BUFFER) {
2782  VkDescriptorGetInfoEXT desc_get_info = {
2783  .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_GET_INFO_EXT,
2784  .type = desc_set->binding[bind].descriptorType,
2785  };
2786  VkDescriptorAddressInfoEXT desc_buf_info = {
2787  .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_ADDRESS_INFO_EXT,
2788  .address = buf->address + offset,
2789  .range = len,
2790  .format = fmt,
2791  };
2792  size_t desc_size;
2793 
2794  switch (desc_get_info.type) {
2795  case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
2796  desc_get_info.data.pUniformBuffer = &desc_buf_info;
2797  desc_size = s->desc_buf_props.uniformBufferDescriptorSize;
2798  break;
2799  case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
2800  desc_get_info.data.pStorageBuffer = &desc_buf_info;
2801  desc_size = s->desc_buf_props.storageBufferDescriptorSize;
2802  break;
2803  case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
2804  desc_get_info.data.pUniformTexelBuffer = &desc_buf_info;
2805  desc_size = s->desc_buf_props.uniformTexelBufferDescriptorSize;
2806  break;
2807  case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
2808  desc_get_info.data.pStorageTexelBuffer = &desc_buf_info;
2809  desc_size = s->desc_buf_props.storageTexelBufferDescriptorSize;
2810  break;
2811  default:
2812  av_log(s, AV_LOG_ERROR, "Invalid descriptor type at set %i binding %i: %i!\n",
2813  set, bind, desc_get_info.type);
2814  return AVERROR(EINVAL);
2815  break;
2816  };
2817 
2818  update_set_descriptor(s, e, shd, set, bind, elem, &desc_get_info, desc_size);
2819  } else {
2820  VkDescriptorBufferInfo desc_pool_write_info_buf = {
2821  .buffer = buf->buf,
2822  .offset = buf->virtual_offset + offset,
2823  .range = len,
2824  };
2825  VkWriteDescriptorSet desc_pool_write_info = {
2826  .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
2827  .dstBinding = bind,
2828  .descriptorCount = 1,
2829  .dstArrayElement = elem,
2830  .descriptorType = desc_set->binding[bind].descriptorType,
2831  .pBufferInfo = &desc_pool_write_info_buf,
2832  };
2833  update_set_pool_write(s, e, shd, set, &desc_pool_write_info);
2834  }
2835 
2836  return 0;
2837 }
2838 
2840  FFVulkanShader *shd,
2841  VkShaderStageFlagBits stage,
2842  int offset, size_t size, void *src)
2843 {
2844  FFVulkanFunctions *vk = &s->vkfn;
2845  vk->CmdPushConstants(e->buf, shd->pipeline_layout,
2846  stage, offset, size, src);
2847 }
2848 
2850  FFVulkanShader *shd)
2851 {
2852  FFVulkanFunctions *vk = &s->vkfn;
2853  VkDeviceSize offsets[1024];
2854  FFVulkanShaderData *sd = get_shd_data(e, shd);
2855 
2856  if (s->extensions & FF_VK_EXT_SHADER_OBJECT) {
2857  VkShaderStageFlagBits stages = shd->stage;
2858  vk->CmdBindShadersEXT(e->buf, 1, &stages, &shd->object);
2859  } else {
2860  vk->CmdBindPipeline(e->buf, shd->bind_point, shd->pipeline);
2861  }
2862 
2863  if (sd && sd->nb_descriptor_sets) {
2864  if (s->extensions & FF_VK_EXT_DESCRIPTOR_BUFFER) {
2865  for (int i = 0; i < sd->nb_descriptor_sets; i++)
2866  offsets[i] = shd->desc_set[i].singular ? 0 : shd->desc_set[i].aligned_size*e->idx;
2867 
2868  /* Bind descriptor buffers */
2869  vk->CmdBindDescriptorBuffersEXT(e->buf, sd->nb_descriptor_sets, sd->desc_bind);
2870  /* Binding offsets */
2871  vk->CmdSetDescriptorBufferOffsetsEXT(e->buf, shd->bind_point, shd->pipeline_layout,
2872  0, sd->nb_descriptor_sets,
2874  } else if (!shd->use_push) {
2875  vk->CmdBindDescriptorSets(e->buf, shd->bind_point, shd->pipeline_layout,
2876  0, sd->nb_descriptor_sets,
2877  &sd->desc_sets[e->idx*sd->nb_descriptor_sets],
2878  0, NULL);
2879  }
2880  }
2881 }
2882 
2884 {
2885  FFVulkanFunctions *vk = &s->vkfn;
2886 
2887  av_bprint_finalize(&shd->src, NULL);
2888 
2889 #if 0
2890  if (shd->shader.module)
2891  vk->DestroyShaderModule(s->hwctx->act_dev, shd->shader.module,
2892  s->hwctx->alloc);
2893 #endif
2894 
2895  if (shd->object)
2896  vk->DestroyShaderEXT(s->hwctx->act_dev, shd->object, s->hwctx->alloc);
2897  if (shd->pipeline)
2898  vk->DestroyPipeline(s->hwctx->act_dev, shd->pipeline, s->hwctx->alloc);
2899  if (shd->pipeline_layout)
2900  vk->DestroyPipelineLayout(s->hwctx->act_dev, shd->pipeline_layout,
2901  s->hwctx->alloc);
2902 
2903  for (int i = 0; i < shd->nb_descriptor_sets; i++) {
2904  FFVulkanDescriptorSet *set = &shd->desc_set[i];
2905  av_free(set->binding);
2906  av_free(set->binding_offset);
2907  }
2908 
2909  if (shd->desc_layout) {
2910  for (int i = 0; i < shd->nb_descriptor_sets; i++)
2911  if (shd->desc_layout[i])
2912  vk->DestroyDescriptorSetLayout(s->hwctx->act_dev, shd->desc_layout[i],
2913  s->hwctx->alloc);
2914  }
2915 
2916  av_freep(&shd->desc_pool_size);
2917  av_freep(&shd->desc_layout);
2918  av_freep(&shd->desc_set);
2920  av_freep(&shd->push_consts);
2921  shd->push_consts_num = 0;
2922 }
2923 
2925 {
2926  av_freep(&s->query_props);
2927  av_freep(&s->qf_props);
2928  av_freep(&s->video_props);
2929  av_freep(&s->coop_mat_props);
2930 
2931  av_buffer_unref(&s->device_ref);
2932  av_buffer_unref(&s->frames_ref);
2933 }
2934 
2935 int ff_vk_init(FFVulkanContext *s, void *log_parent,
2936  AVBufferRef *device_ref, AVBufferRef *frames_ref)
2937 {
2938  int err;
2939 
2940  static const AVClass vulkan_context_class = {
2941  .class_name = "vk",
2942  .version = LIBAVUTIL_VERSION_INT,
2943  .parent_log_context_offset = offsetof(FFVulkanContext, log_parent),
2944  };
2945 
2946  memset(s, 0, sizeof(*s));
2947  s->log_parent = log_parent;
2948  s->class = &vulkan_context_class;
2949 
2950  if (frames_ref) {
2951  s->frames_ref = av_buffer_ref(frames_ref);
2952  if (!s->frames_ref)
2953  return AVERROR(ENOMEM);
2954 
2955  s->frames = (AVHWFramesContext *)s->frames_ref->data;
2956  s->hwfc = s->frames->hwctx;
2957 
2958  device_ref = s->frames->device_ref;
2959  }
2960 
2961  s->device_ref = av_buffer_ref(device_ref);
2962  if (!s->device_ref) {
2963  ff_vk_uninit(s);
2964  return AVERROR(ENOMEM);
2965  }
2966 
2967  s->device = (AVHWDeviceContext *)s->device_ref->data;
2968  s->hwctx = s->device->hwctx;
2969 
2970  s->extensions = ff_vk_extensions_to_mask(s->hwctx->enabled_dev_extensions,
2971  s->hwctx->nb_enabled_dev_extensions);
2972  s->extensions |= ff_vk_extensions_to_mask(s->hwctx->enabled_inst_extensions,
2973  s->hwctx->nb_enabled_inst_extensions);
2974 
2975  err = ff_vk_load_functions(s->device, &s->vkfn, s->extensions, 1, 1);
2976  if (err < 0) {
2977  ff_vk_uninit(s);
2978  return err;
2979  }
2980 
2981  err = ff_vk_load_props(s);
2982  if (err < 0) {
2983  ff_vk_uninit(s);
2984  return err;
2985  }
2986 
2987  return 0;
2988 }
FFVulkanShader::bind_point
VkPipelineBindPoint bind_point
Definition: vulkan.h:202
flags
const SwsFlags flags[]
Definition: swscale.c:61
vulkan_loader.h
AV_PIX_FMT_YUVA422P16
#define AV_PIX_FMT_YUVA422P16
Definition: pixfmt.h:579
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:1736
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:2883
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:2016
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:54
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:2370
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
AV_PIX_FMT_YUVA420P16
#define AV_PIX_FMT_YUVA420P16
Definition: pixfmt.h:578
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
AV_PIX_FMT_YUVA420P10
#define AV_PIX_FMT_YUVA420P10
Definition: pixfmt.h:573
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:1203
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:2935
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:2924
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:2695
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
AV_PIX_FMT_YUVA422P10
#define AV_PIX_FMT_YUVA422P10
Definition: pixfmt.h:574
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:2369
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:1735
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:1315
fail
#define fail()
Definition: checkasm.h:196
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
AV_PIX_FMT_YUVA444P16
#define AV_PIX_FMT_YUVA444P16
Definition: pixfmt.h:580
ff_vk_unmap_buffers
int ff_vk_unmap_buffers(FFVulkanContext *s, FFVkBuffer **buf, int nb_buffers, int flush)
Definition: vulkan.c:1132
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:2760
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:2523
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:1323
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:2388
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:2146
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:1473
FFVkExecPool::query_statuses
int query_statuses
Definition: vulkan.h:263
descriptor_props::struct_size
size_t struct_size
Definition: vulkan.c:2368
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:2248
init_pipeline_layout
static int init_pipeline_layout(FFVulkanContext *s, FFVulkanShader *shd)
Definition: vulkan.c:2120
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_YUVA420P
@ AV_PIX_FMT_YUVA420P
planar YUV 4:2:0, 20bpp, (1 Cr & Cb sample per 2x2 Y & A samples)
Definition: pixfmt.h:108
AV_PIX_FMT_RGB96
#define AV_PIX_FMT_RGB96
Definition: pixfmt.h: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:112
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:2649
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:1512
av_assert0
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition: avassert.h:41
create_mapped_buffer
static int create_mapped_buffer(FFVulkanContext *s, FFVkBuffer *vkb, VkBufferUsageFlags usage, size_t size, VkExternalMemoryBufferCreateInfo *create_desc, VkImportMemoryHostPointerInfoEXT *import_desc, VkMemoryHostPointerPropertiesEXT props)
Definition: vulkan.c:1269
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_PIX_FMT_YUVA444P12
#define AV_PIX_FMT_YUVA444P12
Definition: pixfmt.h:577
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:1737
map_fmt_to_rep
static VkFormat map_fmt_to_rep(VkFormat fmt, enum FFVkShaderRepFormat rep_fmt)
Definition: vulkan.c:1752
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:1550
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:2371
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:2372
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:2172
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:1839
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:1740
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:2839
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:68
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:2668
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
AV_PIX_FMT_YUVA444P
@ AV_PIX_FMT_YUVA444P
planar YUV 4:4:4 32bpp, (1 Cr & Cb sample per 1x1 Y & A samples)
Definition: pixfmt.h:174
AVVkFrame::queue_family
uint32_t queue_family[AV_NUM_DATA_POINTERS]
Queue family of the images.
Definition: hwcontext_vulkan.h:361
AVVulkanDeviceQueueFamily::idx
int idx
Definition: hwcontext_vulkan.h:35
AV_PIX_FMT_YUVA444P10
#define AV_PIX_FMT_YUVA444P10
Definition: pixfmt.h:575
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:2773
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:1490
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:2367
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:1973
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:2313
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:1174
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:2849
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:1890
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:2373
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:1420
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:1195
GLSLF
#define GLSLF(N, S,...)
Definition: vulkan.h:53
AV_PIX_FMT_YUVA422P12
#define AV_PIX_FMT_YUVA422P12
Definition: pixfmt.h:576
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:2098
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:1441
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:2207
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:2640
CASE
#define CASE(VAL)
FFVulkanFunctions
Definition: vulkan_functions.h:268
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:1216
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:1085
FFVkExecContext::idx
uint32_t idx
Definition: vulkan.h:112
src
#define src
Definition: vp8dsp.c:248
AV_PIX_FMT_YUVA422P
@ AV_PIX_FMT_YUVA422P
planar YUV 4:2:2 24bpp, (1 Cr & Cb sample per 2x1 Y & A samples)
Definition: pixfmt.h:173
FN_MAP_TO
#define FN_MAP_TO(dst_t, dst_name, src_t, src_name)
Definition: vulkan.c:88
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