FFmpeg
vulkan.c
Go to the documentation of this file.
1 /*
2  * This file is part of FFmpeg.
3  *
4  * FFmpeg is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * FFmpeg is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with FFmpeg; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17  */
18 
19 #include "avassert.h"
20 
21 #include "vulkan.h"
22 #include "vulkan_loader.h"
23 
24 #if CONFIG_LIBGLSLANG
25 #include "vulkan_glslang.c"
26 #elif CONFIG_LIBSHADERC
27 #include "vulkan_shaderc.c"
28 #endif
29 
30 /* Generic macro for creating contexts which need to keep their addresses
31  * if another context is created. */
32 #define FN_CREATING(ctx, type, shortname, array, num) \
33 static av_always_inline type *create_ ##shortname(ctx *dctx) \
34 { \
35  type **array, *sctx = av_mallocz(sizeof(*sctx)); \
36  if (!sctx) \
37  return NULL; \
38  \
39  array = av_realloc_array(dctx->array, sizeof(*dctx->array), dctx->num + 1);\
40  if (!array) { \
41  av_free(sctx); \
42  return NULL; \
43  } \
44  \
45  dctx->array = array; \
46  dctx->array[dctx->num++] = sctx; \
47  \
48  return sctx; \
49 }
50 
51 const VkComponentMapping ff_comp_identity_map = {
52  .r = VK_COMPONENT_SWIZZLE_IDENTITY,
53  .g = VK_COMPONENT_SWIZZLE_IDENTITY,
54  .b = VK_COMPONENT_SWIZZLE_IDENTITY,
55  .a = VK_COMPONENT_SWIZZLE_IDENTITY,
56 };
57 
58 /* Converts return values to strings */
59 const char *ff_vk_ret2str(VkResult res)
60 {
61 #define CASE(VAL) case VAL: return #VAL
62  switch (res) {
63  CASE(VK_SUCCESS);
64  CASE(VK_NOT_READY);
65  CASE(VK_TIMEOUT);
66  CASE(VK_EVENT_SET);
67  CASE(VK_EVENT_RESET);
68  CASE(VK_INCOMPLETE);
69  CASE(VK_ERROR_OUT_OF_HOST_MEMORY);
70  CASE(VK_ERROR_OUT_OF_DEVICE_MEMORY);
71  CASE(VK_ERROR_INITIALIZATION_FAILED);
72  CASE(VK_ERROR_DEVICE_LOST);
73  CASE(VK_ERROR_MEMORY_MAP_FAILED);
74  CASE(VK_ERROR_LAYER_NOT_PRESENT);
75  CASE(VK_ERROR_EXTENSION_NOT_PRESENT);
76  CASE(VK_ERROR_FEATURE_NOT_PRESENT);
77  CASE(VK_ERROR_INCOMPATIBLE_DRIVER);
78  CASE(VK_ERROR_TOO_MANY_OBJECTS);
79  CASE(VK_ERROR_FORMAT_NOT_SUPPORTED);
80  CASE(VK_ERROR_FRAGMENTED_POOL);
81  CASE(VK_ERROR_SURFACE_LOST_KHR);
82  CASE(VK_ERROR_NATIVE_WINDOW_IN_USE_KHR);
83  CASE(VK_SUBOPTIMAL_KHR);
84  CASE(VK_ERROR_OUT_OF_DATE_KHR);
85  CASE(VK_ERROR_INCOMPATIBLE_DISPLAY_KHR);
86  CASE(VK_ERROR_VALIDATION_FAILED_EXT);
87  CASE(VK_ERROR_INVALID_SHADER_NV);
88  CASE(VK_ERROR_OUT_OF_POOL_MEMORY);
89  CASE(VK_ERROR_INVALID_EXTERNAL_HANDLE);
90  CASE(VK_ERROR_NOT_PERMITTED_EXT);
91  default: return "Unknown error";
92  }
93 #undef CASE
94 }
95 
97  VkQueueFlagBits dev_family, int nb_queues)
98 {
99  switch (dev_family) {
100  case VK_QUEUE_GRAPHICS_BIT:
101  qf->queue_family = s->hwctx->queue_family_index;
102  qf->actual_queues = s->hwctx->nb_graphics_queues;
103  break;
104  case VK_QUEUE_COMPUTE_BIT:
105  qf->queue_family = s->hwctx->queue_family_comp_index;
106  qf->actual_queues = s->hwctx->nb_comp_queues;
107  break;
108  case VK_QUEUE_TRANSFER_BIT:
109  qf->queue_family = s->hwctx->queue_family_tx_index;
110  qf->actual_queues = s->hwctx->nb_tx_queues;
111  break;
112  case VK_QUEUE_VIDEO_ENCODE_BIT_KHR:
113  qf->queue_family = s->hwctx->queue_family_encode_index;
114  qf->actual_queues = s->hwctx->nb_encode_queues;
115  break;
116  case VK_QUEUE_VIDEO_DECODE_BIT_KHR:
117  qf->queue_family = s->hwctx->queue_family_decode_index;
118  qf->actual_queues = s->hwctx->nb_decode_queues;
119  break;
120  default:
121  av_assert0(0); /* Should never happen */
122  }
123 
124  if (!nb_queues)
125  qf->nb_queues = qf->actual_queues;
126  else
127  qf->nb_queues = nb_queues;
128 
129  return;
130 }
131 
133 {
134  qf->cur_queue = (qf->cur_queue + 1) % qf->nb_queues;
135 }
136 
137 static int vk_alloc_mem(FFVulkanContext *s, VkMemoryRequirements *req,
138  VkMemoryPropertyFlagBits req_flags, void *alloc_extension,
139  VkMemoryPropertyFlagBits *mem_flags, VkDeviceMemory *mem)
140 {
141  VkResult ret;
142  int index = -1;
143  FFVulkanFunctions *vk = &s->vkfn;
144 
145  VkMemoryAllocateInfo alloc_info = {
146  .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
147  .pNext = alloc_extension,
148  };
149 
150  /* Align if we need to */
151  if (req_flags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT)
152  req->size = FFALIGN(req->size, s->props.limits.minMemoryMapAlignment);
153 
154  alloc_info.allocationSize = req->size;
155 
156  /* The vulkan spec requires memory types to be sorted in the "optimal"
157  * order, so the first matching type we find will be the best/fastest one */
158  for (int i = 0; i < s->mprops.memoryTypeCount; i++) {
159  /* The memory type must be supported by the requirements (bitfield) */
160  if (!(req->memoryTypeBits & (1 << i)))
161  continue;
162 
163  /* The memory type flags must include our properties */
164  if ((s->mprops.memoryTypes[i].propertyFlags & req_flags) != req_flags)
165  continue;
166 
167  /* Found a suitable memory type */
168  index = i;
169  break;
170  }
171 
172  if (index < 0) {
173  av_log(s, AV_LOG_ERROR, "No memory type found for flags 0x%x\n",
174  req_flags);
175  return AVERROR(EINVAL);
176  }
177 
178  alloc_info.memoryTypeIndex = index;
179 
180  ret = vk->AllocateMemory(s->hwctx->act_dev, &alloc_info,
181  s->hwctx->alloc, mem);
182  if (ret != VK_SUCCESS) {
183  av_log(s, AV_LOG_ERROR, "Failed to allocate memory: %s\n",
184  ff_vk_ret2str(ret));
185  return AVERROR(ENOMEM);
186  }
187 
188  *mem_flags |= s->mprops.memoryTypes[index].propertyFlags;
189 
190  return 0;
191 }
192 
194  VkBufferUsageFlags usage, VkMemoryPropertyFlagBits flags)
195 {
196  int err;
197  VkResult ret;
198  int use_ded_mem;
199  FFVulkanFunctions *vk = &s->vkfn;
200 
201  VkBufferCreateInfo buf_spawn = {
202  .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
203  .pNext = NULL,
204  .usage = usage,
205  .sharingMode = VK_SHARING_MODE_EXCLUSIVE,
206  .size = size, /* Gets FFALIGNED during alloc if host visible
207  but should be ok */
208  };
209 
210  VkBufferMemoryRequirementsInfo2 req_desc = {
211  .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_REQUIREMENTS_INFO_2,
212  };
213  VkMemoryDedicatedAllocateInfo ded_alloc = {
214  .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO,
215  .pNext = NULL,
216  };
217  VkMemoryDedicatedRequirements ded_req = {
218  .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS,
219  };
220  VkMemoryRequirements2 req = {
221  .sType = VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2,
222  .pNext = &ded_req,
223  };
224 
225  ret = vk->CreateBuffer(s->hwctx->act_dev, &buf_spawn, NULL, &buf->buf);
226  if (ret != VK_SUCCESS) {
227  av_log(s, AV_LOG_ERROR, "Failed to create buffer: %s\n",
228  ff_vk_ret2str(ret));
229  return AVERROR_EXTERNAL;
230  }
231 
232  req_desc.buffer = buf->buf;
233 
234  vk->GetBufferMemoryRequirements2(s->hwctx->act_dev, &req_desc, &req);
235 
236  /* In case the implementation prefers/requires dedicated allocation */
237  use_ded_mem = ded_req.prefersDedicatedAllocation |
238  ded_req.requiresDedicatedAllocation;
239  if (use_ded_mem)
240  ded_alloc.buffer = buf->buf;
241 
242  err = vk_alloc_mem(s, &req.memoryRequirements, flags,
243  use_ded_mem ? &ded_alloc : (void *)ded_alloc.pNext,
244  &buf->flags, &buf->mem);
245  if (err)
246  return err;
247 
248  ret = vk->BindBufferMemory(s->hwctx->act_dev, buf->buf, buf->mem, 0);
249  if (ret != VK_SUCCESS) {
250  av_log(s, AV_LOG_ERROR, "Failed to bind memory to buffer: %s\n",
251  ff_vk_ret2str(ret));
252  return AVERROR_EXTERNAL;
253  }
254 
255  return 0;
256 }
257 
258 int ff_vk_map_buffers(FFVulkanContext *s, FFVkBuffer *buf, uint8_t *mem[],
259  int nb_buffers, int invalidate)
260 {
261  VkResult ret;
262  FFVulkanFunctions *vk = &s->vkfn;
263  VkMappedMemoryRange *inval_list = NULL;
264  int inval_count = 0;
265 
266  for (int i = 0; i < nb_buffers; i++) {
267  ret = vk->MapMemory(s->hwctx->act_dev, buf[i].mem, 0,
268  VK_WHOLE_SIZE, 0, (void **)&mem[i]);
269  if (ret != VK_SUCCESS) {
270  av_log(s, AV_LOG_ERROR, "Failed to map buffer memory: %s\n",
271  ff_vk_ret2str(ret));
272  return AVERROR_EXTERNAL;
273  }
274  }
275 
276  if (!invalidate)
277  return 0;
278 
279  for (int i = 0; i < nb_buffers; i++) {
280  const VkMappedMemoryRange ival_buf = {
281  .sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,
282  .memory = buf[i].mem,
283  .size = VK_WHOLE_SIZE,
284  };
285  if (buf[i].flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)
286  continue;
287  inval_list = av_fast_realloc(s->scratch, &s->scratch_size,
288  (++inval_count)*sizeof(*inval_list));
289  if (!inval_list)
290  return AVERROR(ENOMEM);
291  inval_list[inval_count - 1] = ival_buf;
292  }
293 
294  if (inval_count) {
295  ret = vk->InvalidateMappedMemoryRanges(s->hwctx->act_dev, inval_count,
296  inval_list);
297  if (ret != VK_SUCCESS) {
298  av_log(s, AV_LOG_ERROR, "Failed to invalidate memory: %s\n",
299  ff_vk_ret2str(ret));
300  return AVERROR_EXTERNAL;
301  }
302  }
303 
304  return 0;
305 }
306 
307 int ff_vk_unmap_buffers(FFVulkanContext *s, FFVkBuffer *buf, int nb_buffers,
308  int flush)
309 {
310  int err = 0;
311  VkResult ret;
312  FFVulkanFunctions *vk = &s->vkfn;
313  VkMappedMemoryRange *flush_list = NULL;
314  int flush_count = 0;
315 
316  if (flush) {
317  for (int i = 0; i < nb_buffers; i++) {
318  const VkMappedMemoryRange flush_buf = {
319  .sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,
320  .memory = buf[i].mem,
321  .size = VK_WHOLE_SIZE,
322  };
323  if (buf[i].flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)
324  continue;
325  flush_list = av_fast_realloc(s->scratch, &s->scratch_size,
326  (++flush_count)*sizeof(*flush_list));
327  if (!flush_list)
328  return AVERROR(ENOMEM);
329  flush_list[flush_count - 1] = flush_buf;
330  }
331  }
332 
333  if (flush_count) {
334  ret = vk->FlushMappedMemoryRanges(s->hwctx->act_dev, flush_count,
335  flush_list);
336  if (ret != VK_SUCCESS) {
337  av_log(s, AV_LOG_ERROR, "Failed to flush memory: %s\n",
338  ff_vk_ret2str(ret));
339  err = AVERROR_EXTERNAL; /* We still want to try to unmap them */
340  }
341  }
342 
343  for (int i = 0; i < nb_buffers; i++)
344  vk->UnmapMemory(s->hwctx->act_dev, buf[i].mem);
345 
346  return err;
347 }
348 
350 {
351  FFVulkanFunctions *vk = &s->vkfn;
352 
353  if (!buf || !s->hwctx)
354  return;
355 
356  vk->DeviceWaitIdle(s->hwctx->act_dev);
357 
358  if (buf->buf != VK_NULL_HANDLE)
359  vk->DestroyBuffer(s->hwctx->act_dev, buf->buf, s->hwctx->alloc);
360  if (buf->mem != VK_NULL_HANDLE)
361  vk->FreeMemory(s->hwctx->act_dev, buf->mem, s->hwctx->alloc);
362 }
363 
365  VkShaderStageFlagBits stage)
366 {
367  VkPushConstantRange *pc;
368 
369  pl->push_consts = av_realloc_array(pl->push_consts, sizeof(*pl->push_consts),
370  pl->push_consts_num + 1);
371  if (!pl->push_consts)
372  return AVERROR(ENOMEM);
373 
374  pc = &pl->push_consts[pl->push_consts_num++];
375  memset(pc, 0, sizeof(*pc));
376 
377  pc->stageFlags = stage;
378  pc->offset = offset;
379  pc->size = size;
380 
381  return 0;
382 }
383 
384 FN_CREATING(FFVulkanContext, FFVkExecContext, exec_ctx, exec_ctx, exec_ctx_num)
386  FFVkQueueFamilyCtx *qf)
387 {
388  VkResult ret;
389  FFVkExecContext *e;
390  FFVulkanFunctions *vk = &s->vkfn;
391 
392  VkCommandPoolCreateInfo cqueue_create = {
393  .sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
394  .flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,
395  .queueFamilyIndex = qf->queue_family,
396  };
397  VkCommandBufferAllocateInfo cbuf_create = {
398  .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
399  .level = VK_COMMAND_BUFFER_LEVEL_PRIMARY,
400  .commandBufferCount = qf->nb_queues,
401  };
402 
403  e = create_exec_ctx(s);
404  if (!e)
405  return AVERROR(ENOMEM);
406 
407  e->qf = qf;
408 
409  e->queues = av_mallocz(qf->nb_queues * sizeof(*e->queues));
410  if (!e->queues)
411  return AVERROR(ENOMEM);
412 
413  e->bufs = av_mallocz(qf->nb_queues * sizeof(*e->bufs));
414  if (!e->bufs)
415  return AVERROR(ENOMEM);
416 
417  /* Create command pool */
418  ret = vk->CreateCommandPool(s->hwctx->act_dev, &cqueue_create,
419  s->hwctx->alloc, &e->pool);
420  if (ret != VK_SUCCESS) {
421  av_log(s, AV_LOG_ERROR, "Command pool creation failure: %s\n",
422  ff_vk_ret2str(ret));
423  return AVERROR_EXTERNAL;
424  }
425 
426  cbuf_create.commandPool = e->pool;
427 
428  /* Allocate command buffer */
429  ret = vk->AllocateCommandBuffers(s->hwctx->act_dev, &cbuf_create, e->bufs);
430  if (ret != VK_SUCCESS) {
431  av_log(s, AV_LOG_ERROR, "Command buffer alloc failure: %s\n",
432  ff_vk_ret2str(ret));
433  return AVERROR_EXTERNAL;
434  }
435 
436  for (int i = 0; i < qf->nb_queues; i++) {
437  FFVkQueueCtx *q = &e->queues[i];
438  vk->GetDeviceQueue(s->hwctx->act_dev, qf->queue_family,
439  i % qf->actual_queues, &q->queue);
440  }
441 
442  *ctx = e;
443 
444  return 0;
445 }
446 
448 {
449  FFVkQueueCtx *q = &e->queues[e->qf->cur_queue];
450 
451  for (int j = 0; j < q->nb_buf_deps; j++)
452  av_buffer_unref(&q->buf_deps[j]);
453  q->nb_buf_deps = 0;
454 
455  for (int j = 0; j < q->nb_frame_deps; j++)
456  av_frame_free(&q->frame_deps[j]);
457  q->nb_frame_deps = 0;
458 
459  e->sem_wait_cnt = 0;
460  e->sem_sig_cnt = 0;
461 }
462 
464 {
465  VkResult ret;
466  FFVulkanFunctions *vk = &s->vkfn;
467  FFVkQueueCtx *q = &e->queues[e->qf->cur_queue];
468 
469  VkCommandBufferBeginInfo cmd_start = {
470  .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
471  .flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,
472  };
473 
474  /* Create the fence and don't wait for it initially */
475  if (!q->fence) {
476  VkFenceCreateInfo fence_spawn = {
477  .sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,
478  };
479  ret = vk->CreateFence(s->hwctx->act_dev, &fence_spawn, s->hwctx->alloc,
480  &q->fence);
481  if (ret != VK_SUCCESS) {
482  av_log(s, AV_LOG_ERROR, "Failed to queue frame fence: %s\n",
483  ff_vk_ret2str(ret));
484  return AVERROR_EXTERNAL;
485  }
486  } else {
487  vk->WaitForFences(s->hwctx->act_dev, 1, &q->fence, VK_TRUE, UINT64_MAX);
488  vk->ResetFences(s->hwctx->act_dev, 1, &q->fence);
489  }
490 
491  /* Discard queue dependencies */
493 
494  ret = vk->BeginCommandBuffer(e->bufs[e->qf->cur_queue], &cmd_start);
495  if (ret != VK_SUCCESS) {
496  av_log(s, AV_LOG_ERROR, "Failed to start command recoding: %s\n",
497  ff_vk_ret2str(ret));
498  return AVERROR_EXTERNAL;
499  }
500 
501  return 0;
502 }
503 
505 {
506  return e->bufs[e->qf->cur_queue];
507 }
508 
510  VkPipelineStageFlagBits in_wait_dst_flag)
511 {
512  AVFrame **dst;
513  AVVkFrame *f = (AVVkFrame *)frame->data[0];
514  FFVkQueueCtx *q = &e->queues[e->qf->cur_queue];
515  AVHWFramesContext *fc = (AVHWFramesContext *)frame->hw_frames_ctx->data;
516  int planes = av_pix_fmt_count_planes(fc->sw_format);
517 
518  for (int i = 0; i < planes; i++) {
520  (e->sem_wait_cnt + 1)*sizeof(*e->sem_wait));
521  if (!e->sem_wait) {
523  return AVERROR(ENOMEM);
524  }
525 
527  (e->sem_wait_cnt + 1)*sizeof(*e->sem_wait_dst));
528  if (!e->sem_wait_dst) {
530  return AVERROR(ENOMEM);
531  }
532 
534  (e->sem_wait_cnt + 1)*sizeof(*e->sem_wait_val));
535  if (!e->sem_wait_val) {
537  return AVERROR(ENOMEM);
538  }
539 
541  (e->sem_sig_cnt + 1)*sizeof(*e->sem_sig));
542  if (!e->sem_sig) {
544  return AVERROR(ENOMEM);
545  }
546 
548  (e->sem_sig_cnt + 1)*sizeof(*e->sem_sig_val));
549  if (!e->sem_sig_val) {
551  return AVERROR(ENOMEM);
552  }
553 
555  (e->sem_sig_cnt + 1)*sizeof(*e->sem_sig_val_dst));
556  if (!e->sem_sig_val_dst) {
558  return AVERROR(ENOMEM);
559  }
560 
561  e->sem_wait[e->sem_wait_cnt] = f->sem[i];
562  e->sem_wait_dst[e->sem_wait_cnt] = in_wait_dst_flag;
563  e->sem_wait_val[e->sem_wait_cnt] = f->sem_value[i];
564  e->sem_wait_cnt++;
565 
566  e->sem_sig[e->sem_sig_cnt] = f->sem[i];
567  e->sem_sig_val[e->sem_sig_cnt] = f->sem_value[i] + 1;
568  e->sem_sig_val_dst[e->sem_sig_cnt] = &f->sem_value[i];
569  e->sem_sig_cnt++;
570  }
571 
572  dst = av_fast_realloc(q->frame_deps, &q->frame_deps_alloc_size,
573  (q->nb_frame_deps + 1) * sizeof(*dst));
574  if (!dst) {
576  return AVERROR(ENOMEM);
577  }
578 
579  q->frame_deps = dst;
580  q->frame_deps[q->nb_frame_deps] = av_frame_clone(frame);
581  if (!q->frame_deps[q->nb_frame_deps]) {
583  return AVERROR(ENOMEM);
584  }
585  q->nb_frame_deps++;
586 
587  return 0;
588 }
589 
591 {
592  VkResult ret;
593  FFVulkanFunctions *vk = &s->vkfn;
594  FFVkQueueCtx *q = &e->queues[e->qf->cur_queue];
595 
596  VkTimelineSemaphoreSubmitInfo s_timeline_sem_info = {
597  .sType = VK_STRUCTURE_TYPE_TIMELINE_SEMAPHORE_SUBMIT_INFO,
598  .pWaitSemaphoreValues = e->sem_wait_val,
599  .pSignalSemaphoreValues = e->sem_sig_val,
600  .waitSemaphoreValueCount = e->sem_wait_cnt,
601  .signalSemaphoreValueCount = e->sem_sig_cnt,
602  };
603 
604  VkSubmitInfo s_info = {
605  .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,
606  .pNext = &s_timeline_sem_info,
607 
608  .commandBufferCount = 1,
609  .pCommandBuffers = &e->bufs[e->qf->cur_queue],
610 
611  .pWaitSemaphores = e->sem_wait,
612  .pWaitDstStageMask = e->sem_wait_dst,
613  .waitSemaphoreCount = e->sem_wait_cnt,
614 
615  .pSignalSemaphores = e->sem_sig,
616  .signalSemaphoreCount = e->sem_sig_cnt,
617  };
618 
619  ret = vk->EndCommandBuffer(e->bufs[e->qf->cur_queue]);
620  if (ret != VK_SUCCESS) {
621  av_log(s, AV_LOG_ERROR, "Unable to finish command buffer: %s\n",
622  ff_vk_ret2str(ret));
623  return AVERROR_EXTERNAL;
624  }
625 
626  ret = vk->QueueSubmit(q->queue, 1, &s_info, q->fence);
627  if (ret != VK_SUCCESS) {
628  av_log(s, AV_LOG_ERROR, "Unable to submit command buffer: %s\n",
629  ff_vk_ret2str(ret));
630  return AVERROR_EXTERNAL;
631  }
632 
633  for (int i = 0; i < e->sem_sig_cnt; i++)
634  *e->sem_sig_val_dst[i] += 1;
635 
636  return 0;
637 }
638 
640  AVBufferRef **deps, int nb_deps)
641 {
642  AVBufferRef **dst;
643  FFVkQueueCtx *q = &e->queues[e->qf->cur_queue];
644 
645  if (!deps || !nb_deps)
646  return 0;
647 
649  (q->nb_buf_deps + nb_deps) * sizeof(*dst));
650  if (!dst)
651  goto err;
652 
653  q->buf_deps = dst;
654 
655  for (int i = 0; i < nb_deps; i++) {
656  q->buf_deps[q->nb_buf_deps] = deps[i];
657  if (!q->buf_deps[q->nb_buf_deps])
658  goto err;
659  q->nb_buf_deps++;
660  }
661 
662  return 0;
663 
664 err:
666  return AVERROR(ENOMEM);
667 }
668 
669 FN_CREATING(FFVulkanContext, FFVkSampler, sampler, samplers, samplers_num)
671  int unnorm_coords, VkFilter filt)
672 {
673  VkResult ret;
674  FFVulkanFunctions *vk = &s->vkfn;
675 
676  VkSamplerCreateInfo sampler_info = {
677  .sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,
678  .magFilter = filt,
679  .minFilter = sampler_info.magFilter,
680  .mipmapMode = unnorm_coords ? VK_SAMPLER_MIPMAP_MODE_NEAREST :
681  VK_SAMPLER_MIPMAP_MODE_LINEAR,
682  .addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
683  .addressModeV = sampler_info.addressModeU,
684  .addressModeW = sampler_info.addressModeU,
685  .anisotropyEnable = VK_FALSE,
686  .compareOp = VK_COMPARE_OP_NEVER,
687  .borderColor = VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK,
688  .unnormalizedCoordinates = unnorm_coords,
689  };
690 
691  FFVkSampler *sctx = create_sampler(s);
692  if (!sctx)
693  return NULL;
694 
695  ret = vk->CreateSampler(s->hwctx->act_dev, &sampler_info,
696  s->hwctx->alloc, &sctx->sampler[0]);
697  if (ret != VK_SUCCESS) {
698  av_log(s, AV_LOG_ERROR, "Unable to init sampler: %s\n",
699  ff_vk_ret2str(ret));
700  return NULL;
701  }
702 
703  for (int i = 1; i < 4; i++)
704  sctx->sampler[i] = sctx->sampler[0];
705 
706  return sctx;
707 }
708 
710 {
717  return 1;
718  return 0;
719 }
720 
722 {
724  const int high = desc->comp[0].depth > 8;
725  return high ? "rgba16f" : "rgba8";
726 }
727 
728 typedef struct ImageViewCtx {
729  VkImageView view;
730 } ImageViewCtx;
731 
732 static void destroy_imageview(void *opaque, uint8_t *data)
733 {
734  FFVulkanContext *s = opaque;
735  FFVulkanFunctions *vk = &s->vkfn;
736  ImageViewCtx *iv = (ImageViewCtx *)data;
737 
738  vk->DestroyImageView(s->hwctx->act_dev, iv->view, s->hwctx->alloc);
739  av_free(iv);
740 }
741 
743  VkImageView *v, VkImage img, VkFormat fmt,
744  const VkComponentMapping map)
745 {
746  int err;
747  AVBufferRef *buf;
748  FFVulkanFunctions *vk = &s->vkfn;
749 
750  VkImageViewCreateInfo imgview_spawn = {
751  .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
752  .pNext = NULL,
753  .image = img,
754  .viewType = VK_IMAGE_VIEW_TYPE_2D,
755  .format = fmt,
756  .components = map,
757  .subresourceRange = {
758  .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
759  .baseMipLevel = 0,
760  .levelCount = 1,
761  .baseArrayLayer = 0,
762  .layerCount = 1,
763  },
764  };
765 
766  ImageViewCtx *iv = av_mallocz(sizeof(*iv));
767 
768  VkResult ret = vk->CreateImageView(s->hwctx->act_dev, &imgview_spawn,
769  s->hwctx->alloc, &iv->view);
770  if (ret != VK_SUCCESS) {
771  av_log(s, AV_LOG_ERROR, "Failed to create imageview: %s\n",
772  ff_vk_ret2str(ret));
773  return AVERROR_EXTERNAL;
774  }
775 
776  buf = av_buffer_create((uint8_t *)iv, sizeof(*iv), destroy_imageview, s, 0);
777  if (!buf) {
778  destroy_imageview(s, (uint8_t *)iv);
779  return AVERROR(ENOMEM);
780  }
781 
782  /* Add to queue dependencies */
783  err = ff_vk_add_dep_exec_ctx(s, e, &buf, 1);
784  if (err) {
785  av_buffer_unref(&buf);
786  return err;
787  }
788 
789  *v = iv->view;
790 
791  return 0;
792 }
793 
794 FN_CREATING(FFVulkanPipeline, FFVkSPIRVShader, shader, shaders, shaders_num)
796  VkShaderStageFlags stage)
797 {
798  FFVkSPIRVShader *shd = create_shader(pl);
799  if (!shd)
800  return NULL;
801 
803 
804  shd->shader.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
805  shd->shader.stage = stage;
806 
807  shd->name = name;
808 
809  GLSLF(0, #version %i ,460);
810  GLSLC(0, #define IS_WITHIN(v1, v2) ((v1.x < v2.x) && (v1.y < v2.y)) );
811  GLSLC(0, );
812 
813  return shd;
814 }
815 
816 void ff_vk_set_compute_shader_sizes(FFVkSPIRVShader *shd, int local_size[3])
817 {
818  shd->local_size[0] = local_size[0];
819  shd->local_size[1] = local_size[1];
820  shd->local_size[2] = local_size[2];
821 
822  av_bprintf(&shd->src, "layout (local_size_x = %i, "
823  "local_size_y = %i, local_size_z = %i) in;\n\n",
824  shd->local_size[0], shd->local_size[1], shd->local_size[2]);
825 }
826 
827 void ff_vk_print_shader(void *ctx, FFVkSPIRVShader *shd, int prio)
828 {
829  int line = 0;
830  const char *p = shd->src.str;
831  const char *start = p;
832 
833  AVBPrint buf;
835 
836  for (int i = 0; i < strlen(p); i++) {
837  if (p[i] == '\n') {
838  av_bprintf(&buf, "%i\t", ++line);
839  av_bprint_append_data(&buf, start, &p[i] - start + 1);
840  start = &p[i + 1];
841  }
842  }
843 
844  av_log(ctx, prio, "Shader %s: \n%s", shd->name, buf.str);
845  av_bprint_finalize(&buf, NULL);
846 }
847 
849  const char *entrypoint)
850 {
851  int err;
852  VkResult ret;
853  FFVulkanFunctions *vk = &s->vkfn;
854  VkShaderModuleCreateInfo shader_create;
855  uint8_t *spirv;
856  size_t spirv_size;
857  void *priv;
858 
859  shd->shader.pName = entrypoint;
860 
861  if (!s->spirv_compiler) {
862 #if CONFIG_LIBGLSLANG
863  s->spirv_compiler = ff_vk_glslang_init();
864 #elif CONFIG_LIBSHADERC
865  s->spirv_compiler = ff_vk_shaderc_init();
866 #else
867  return AVERROR(ENOSYS);
868 #endif
869  if (!s->spirv_compiler)
870  return AVERROR(ENOMEM);
871  }
872 
873  err = s->spirv_compiler->compile_shader(s->spirv_compiler, s, shd, &spirv,
874  &spirv_size, entrypoint, &priv);
875  if (err < 0)
876  return err;
877 
878  av_log(s, AV_LOG_VERBOSE, "Shader %s compiled! Size: %zu bytes\n",
879  shd->name, spirv_size);
880 
881  shader_create.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
882  shader_create.pNext = NULL;
883  shader_create.codeSize = spirv_size;
884  shader_create.flags = 0;
885  shader_create.pCode = (void *)spirv;
886 
887  ret = vk->CreateShaderModule(s->hwctx->act_dev, &shader_create, NULL,
888  &shd->shader.module);
889 
890  s->spirv_compiler->free_shader(s->spirv_compiler, &priv);
891 
892  if (ret != VK_SUCCESS) {
893  av_log(s, AV_LOG_ERROR, "Unable to create shader module: %s\n",
894  ff_vk_ret2str(ret));
895  return AVERROR_EXTERNAL;
896  }
897 
898  return 0;
899 }
900 
901 static const struct descriptor_props {
902  size_t struct_size; /* Size of the opaque which updates the descriptor */
903  const char *type;
905  int mem_quali; /* Can use a memory qualifier */
906  int dim_needed; /* Must indicate dimension */
907  int buf_content; /* Must indicate buffer contents */
908 } descriptor_props[] = {
909  [VK_DESCRIPTOR_TYPE_SAMPLER] = { sizeof(VkDescriptorImageInfo), "sampler", 1, 0, 0, 0, },
910  [VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE] = { sizeof(VkDescriptorImageInfo), "texture", 1, 0, 1, 0, },
911  [VK_DESCRIPTOR_TYPE_STORAGE_IMAGE] = { sizeof(VkDescriptorImageInfo), "image", 1, 1, 1, 0, },
912  [VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT] = { sizeof(VkDescriptorImageInfo), "subpassInput", 1, 0, 0, 0, },
913  [VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER] = { sizeof(VkDescriptorImageInfo), "sampler", 1, 0, 1, 0, },
914  [VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER] = { sizeof(VkDescriptorBufferInfo), NULL, 1, 0, 0, 1, },
915  [VK_DESCRIPTOR_TYPE_STORAGE_BUFFER] = { sizeof(VkDescriptorBufferInfo), "buffer", 0, 1, 0, 1, },
916  [VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC] = { sizeof(VkDescriptorBufferInfo), NULL, 1, 0, 0, 1, },
917  [VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC] = { sizeof(VkDescriptorBufferInfo), "buffer", 0, 1, 0, 1, },
918  [VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER] = { sizeof(VkBufferView), "samplerBuffer", 1, 0, 0, 0, },
919  [VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER] = { sizeof(VkBufferView), "imageBuffer", 1, 0, 0, 0, },
920 };
921 
924  int num, int only_print_to_shader)
925 {
926  VkResult ret;
927  VkDescriptorSetLayout *layout;
928  FFVulkanFunctions *vk = &s->vkfn;
929 
930  if (only_print_to_shader)
931  goto print;
932 
933  pl->desc_layout = av_realloc_array(pl->desc_layout, sizeof(*pl->desc_layout),
934  pl->desc_layout_num + pl->qf->nb_queues);
935  if (!pl->desc_layout)
936  return AVERROR(ENOMEM);
937 
939  sizeof(*pl->desc_set_initialized),
940  pl->descriptor_sets_num + 1);
941  if (!pl->desc_set_initialized)
942  return AVERROR(ENOMEM);
943 
945  layout = &pl->desc_layout[pl->desc_layout_num];
946 
947  { /* Create descriptor set layout descriptions */
948  VkDescriptorSetLayoutCreateInfo desc_create_layout = { 0 };
949  VkDescriptorSetLayoutBinding *desc_binding;
950 
951  desc_binding = av_mallocz(sizeof(*desc_binding)*num);
952  if (!desc_binding)
953  return AVERROR(ENOMEM);
954 
955  for (int i = 0; i < num; i++) {
956  desc_binding[i].binding = i;
957  desc_binding[i].descriptorType = desc[i].type;
958  desc_binding[i].descriptorCount = FFMAX(desc[i].elems, 1);
959  desc_binding[i].stageFlags = desc[i].stages;
960  desc_binding[i].pImmutableSamplers = desc[i].sampler ?
961  desc[i].sampler->sampler :
962  NULL;
963  }
964 
965  desc_create_layout.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
966  desc_create_layout.pBindings = desc_binding;
967  desc_create_layout.bindingCount = num;
968 
969  for (int i = 0; i < pl->qf->nb_queues; i++) {
970  ret = vk->CreateDescriptorSetLayout(s->hwctx->act_dev, &desc_create_layout,
971  s->hwctx->alloc, &layout[i]);
972  if (ret != VK_SUCCESS) {
973  av_log(s, AV_LOG_ERROR, "Unable to init descriptor set "
974  "layout: %s\n", ff_vk_ret2str(ret));
975  av_free(desc_binding);
976  return AVERROR_EXTERNAL;
977  }
978  }
979 
980  av_free(desc_binding);
981  }
982 
983  { /* Pool each descriptor by type and update pool counts */
984  for (int i = 0; i < num; i++) {
985  int j;
986  for (j = 0; j < pl->pool_size_desc_num; j++)
987  if (pl->pool_size_desc[j].type == desc[i].type)
988  break;
989  if (j >= pl->pool_size_desc_num) {
991  sizeof(*pl->pool_size_desc),
992  ++pl->pool_size_desc_num);
993  if (!pl->pool_size_desc)
994  return AVERROR(ENOMEM);
995  memset(&pl->pool_size_desc[j], 0, sizeof(VkDescriptorPoolSize));
996  }
997  pl->pool_size_desc[j].type = desc[i].type;
998  pl->pool_size_desc[j].descriptorCount += FFMAX(desc[i].elems, 1)*pl->qf->nb_queues;
999  }
1000  }
1001 
1002  { /* Create template creation struct */
1003  VkDescriptorUpdateTemplateCreateInfo *dt;
1004  VkDescriptorUpdateTemplateEntry *des_entries;
1005 
1006  /* Freed after descriptor set initialization */
1007  des_entries = av_mallocz(num*sizeof(VkDescriptorUpdateTemplateEntry));
1008  if (!des_entries)
1009  return AVERROR(ENOMEM);
1010 
1011  for (int i = 0; i < num; i++) {
1012  des_entries[i].dstBinding = i;
1013  des_entries[i].descriptorType = desc[i].type;
1014  des_entries[i].descriptorCount = FFMAX(desc[i].elems, 1);
1015  des_entries[i].dstArrayElement = 0;
1016  des_entries[i].offset = ((uint8_t *)desc[i].updater) - (uint8_t *)s;
1017  des_entries[i].stride = descriptor_props[desc[i].type].struct_size;
1018  }
1019 
1021  sizeof(*pl->desc_template_info),
1022  pl->total_descriptor_sets + pl->qf->nb_queues);
1023  if (!pl->desc_template_info)
1024  return AVERROR(ENOMEM);
1025 
1027  memset(dt, 0, sizeof(*dt)*pl->qf->nb_queues);
1028 
1029  for (int i = 0; i < pl->qf->nb_queues; i++) {
1030  dt[i].sType = VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO;
1031  dt[i].templateType = VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET;
1032  dt[i].descriptorSetLayout = layout[i];
1033  dt[i].pDescriptorUpdateEntries = des_entries;
1034  dt[i].descriptorUpdateEntryCount = num;
1035  }
1036  }
1037 
1038  pl->descriptor_sets_num++;
1039 
1040  pl->desc_layout_num += pl->qf->nb_queues;
1041  pl->total_descriptor_sets += pl->qf->nb_queues;
1042 
1043 print:
1044  /* Write shader info */
1045  for (int i = 0; i < num; i++) {
1046  const struct descriptor_props *prop = &descriptor_props[desc[i].type];
1047  GLSLA("layout (set = %i, binding = %i", pl->descriptor_sets_num - 1, i);
1048 
1049  if (desc[i].mem_layout)
1050  GLSLA(", %s", desc[i].mem_layout);
1051  GLSLA(")");
1052 
1053  if (prop->is_uniform)
1054  GLSLA(" uniform");
1055 
1056  if (prop->mem_quali && desc[i].mem_quali)
1057  GLSLA(" %s", desc[i].mem_quali);
1058 
1059  if (prop->type)
1060  GLSLA(" %s", prop->type);
1061 
1062  if (prop->dim_needed)
1063  GLSLA("%iD", desc[i].dimensions);
1064 
1065  GLSLA(" %s", desc[i].name);
1066 
1067  if (prop->buf_content)
1068  GLSLA(" {\n %s\n}", desc[i].buf_content);
1069  else if (desc[i].elems > 0)
1070  GLSLA("[%i]", desc[i].elems);
1071 
1072  GLSLA(";\n");
1073  }
1074  GLSLA("\n");
1075 
1076  return 0;
1077 }
1078 
1080  int set_id)
1081 {
1082  FFVulkanFunctions *vk = &s->vkfn;
1083 
1084  /* If a set has never been updated, update all queues' sets. */
1085  if (!pl->desc_set_initialized[set_id]) {
1086  for (int i = 0; i < pl->qf->nb_queues; i++) {
1087  int idx = set_id*pl->qf->nb_queues + i;
1088  vk->UpdateDescriptorSetWithTemplate(s->hwctx->act_dev,
1089  pl->desc_set[idx],
1090  pl->desc_template[idx],
1091  s);
1092  }
1093  pl->desc_set_initialized[set_id] = 1;
1094  return;
1095  }
1096 
1097  set_id = set_id*pl->qf->nb_queues + pl->qf->cur_queue;
1098 
1099  vk->UpdateDescriptorSetWithTemplate(s->hwctx->act_dev,
1100  pl->desc_set[set_id],
1101  pl->desc_template[set_id],
1102  s);
1103 }
1104 
1106  VkShaderStageFlagBits stage, int offset,
1107  size_t size, void *src)
1108 {
1109  FFVulkanFunctions *vk = &s->vkfn;
1110 
1111  vk->CmdPushConstants(e->bufs[e->qf->cur_queue], e->bound_pl->pipeline_layout,
1112  stage, offset, size, src);
1113 }
1114 
1116 {
1117  VkResult ret;
1118  FFVulkanFunctions *vk = &s->vkfn;
1119 
1120  pl->desc_staging = av_malloc(pl->descriptor_sets_num*sizeof(*pl->desc_staging));
1121  if (!pl->desc_staging)
1122  return AVERROR(ENOMEM);
1123 
1124  { /* Init descriptor set pool */
1125  VkDescriptorPoolCreateInfo pool_create_info = {
1126  .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
1127  .poolSizeCount = pl->pool_size_desc_num,
1128  .pPoolSizes = pl->pool_size_desc,
1129  .maxSets = pl->total_descriptor_sets,
1130  };
1131 
1132  ret = vk->CreateDescriptorPool(s->hwctx->act_dev, &pool_create_info,
1133  s->hwctx->alloc, &pl->desc_pool);
1134  av_freep(&pl->pool_size_desc);
1135  if (ret != VK_SUCCESS) {
1136  av_log(s, AV_LOG_ERROR, "Unable to init descriptor set "
1137  "pool: %s\n", ff_vk_ret2str(ret));
1138  return AVERROR_EXTERNAL;
1139  }
1140  }
1141 
1142  { /* Allocate descriptor sets */
1143  VkDescriptorSetAllocateInfo alloc_info = {
1144  .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
1145  .descriptorPool = pl->desc_pool,
1146  .descriptorSetCount = pl->total_descriptor_sets,
1147  .pSetLayouts = pl->desc_layout,
1148  };
1149 
1150  pl->desc_set = av_malloc(pl->total_descriptor_sets*sizeof(*pl->desc_set));
1151  if (!pl->desc_set)
1152  return AVERROR(ENOMEM);
1153 
1154  ret = vk->AllocateDescriptorSets(s->hwctx->act_dev, &alloc_info,
1155  pl->desc_set);
1156  if (ret != VK_SUCCESS) {
1157  av_log(s, AV_LOG_ERROR, "Unable to allocate descriptor set: %s\n",
1158  ff_vk_ret2str(ret));
1159  return AVERROR_EXTERNAL;
1160  }
1161  }
1162 
1163  { /* Finally create the pipeline layout */
1164  VkPipelineLayoutCreateInfo spawn_pipeline_layout = {
1165  .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
1166  .pSetLayouts = (VkDescriptorSetLayout *)pl->desc_staging,
1167  .pushConstantRangeCount = pl->push_consts_num,
1168  .pPushConstantRanges = pl->push_consts,
1169  };
1170 
1171  for (int i = 0; i < pl->total_descriptor_sets; i += pl->qf->nb_queues)
1172  pl->desc_staging[spawn_pipeline_layout.setLayoutCount++] = pl->desc_layout[i];
1173 
1174  ret = vk->CreatePipelineLayout(s->hwctx->act_dev, &spawn_pipeline_layout,
1175  s->hwctx->alloc, &pl->pipeline_layout);
1176  av_freep(&pl->push_consts);
1177  pl->push_consts_num = 0;
1178  if (ret != VK_SUCCESS) {
1179  av_log(s, AV_LOG_ERROR, "Unable to init pipeline layout: %s\n",
1180  ff_vk_ret2str(ret));
1181  return AVERROR_EXTERNAL;
1182  }
1183  }
1184 
1185  { /* Descriptor template (for tightly packed descriptors) */
1186  VkDescriptorUpdateTemplateCreateInfo *dt;
1187 
1189  if (!pl->desc_template)
1190  return AVERROR(ENOMEM);
1191 
1192  /* Create update templates for the descriptor sets */
1193  for (int i = 0; i < pl->total_descriptor_sets; i++) {
1194  dt = &pl->desc_template_info[i];
1195  dt->pipelineLayout = pl->pipeline_layout;
1196  ret = vk->CreateDescriptorUpdateTemplate(s->hwctx->act_dev,
1197  dt, s->hwctx->alloc,
1198  &pl->desc_template[i]);
1199  if (ret != VK_SUCCESS) {
1200  av_log(s, AV_LOG_ERROR, "Unable to init descriptor "
1201  "template: %s\n", ff_vk_ret2str(ret));
1202  return AVERROR_EXTERNAL;
1203  }
1204  }
1205 
1206  /* Free the duplicated memory used for the template entries */
1207  for (int i = 0; i < pl->total_descriptor_sets; i += pl->qf->nb_queues) {
1208  dt = &pl->desc_template_info[i];
1209  av_free((void *)dt->pDescriptorUpdateEntries);
1210  }
1211 
1213  }
1214 
1215  return 0;
1216 }
1217 
1218 FN_CREATING(FFVulkanContext, FFVulkanPipeline, pipeline, pipelines, pipelines_num)
1220 {
1221  FFVulkanPipeline *pl = create_pipeline(s);
1222  if (pl)
1223  pl->qf = qf;
1224 
1225  return pl;
1226 }
1227 
1229 {
1230  int i;
1231  VkResult ret;
1232  FFVulkanFunctions *vk = &s->vkfn;
1233 
1234  VkComputePipelineCreateInfo pipe = {
1235  .sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,
1236  .layout = pl->pipeline_layout,
1237  };
1238 
1239  for (i = 0; i < pl->shaders_num; i++) {
1240  if (pl->shaders[i]->shader.stage & VK_SHADER_STAGE_COMPUTE_BIT) {
1241  pipe.stage = pl->shaders[i]->shader;
1242  break;
1243  }
1244  }
1245  if (i == pl->shaders_num) {
1246  av_log(s, AV_LOG_ERROR, "Can't init compute pipeline, no shader\n");
1247  return AVERROR(EINVAL);
1248  }
1249 
1250  ret = vk->CreateComputePipelines(s->hwctx->act_dev, VK_NULL_HANDLE, 1, &pipe,
1251  s->hwctx->alloc, &pl->pipeline);
1252  if (ret != VK_SUCCESS) {
1253  av_log(s, AV_LOG_ERROR, "Unable to init compute pipeline: %s\n",
1254  ff_vk_ret2str(ret));
1255  return AVERROR_EXTERNAL;
1256  }
1257 
1258  pl->bind_point = VK_PIPELINE_BIND_POINT_COMPUTE;
1259 
1260  return 0;
1261 }
1262 
1264  FFVulkanPipeline *pl)
1265 {
1266  FFVulkanFunctions *vk = &s->vkfn;
1267 
1268  vk->CmdBindPipeline(e->bufs[e->qf->cur_queue], pl->bind_point, pl->pipeline);
1269 
1270  for (int i = 0; i < pl->descriptor_sets_num; i++)
1271  pl->desc_staging[i] = pl->desc_set[i*pl->qf->nb_queues + pl->qf->cur_queue];
1272 
1273  vk->CmdBindDescriptorSets(e->bufs[e->qf->cur_queue], pl->bind_point,
1274  pl->pipeline_layout, 0,
1275  pl->descriptor_sets_num,
1276  (VkDescriptorSet *)pl->desc_staging,
1277  0, NULL);
1278 
1279  e->bound_pl = pl;
1280 }
1281 
1283 {
1284  FFVulkanFunctions *vk = &s->vkfn;
1285 
1286  /* Make sure all queues have finished executing */
1287  for (int i = 0; i < e->qf->nb_queues; i++) {
1288  FFVkQueueCtx *q = &e->queues[i];
1289 
1290  if (q->fence) {
1291  vk->WaitForFences(s->hwctx->act_dev, 1, &q->fence, VK_TRUE, UINT64_MAX);
1292  vk->ResetFences(s->hwctx->act_dev, 1, &q->fence);
1293  }
1294 
1295  /* Free the fence */
1296  if (q->fence)
1297  vk->DestroyFence(s->hwctx->act_dev, q->fence, s->hwctx->alloc);
1298 
1299  /* Free buffer dependencies */
1300  for (int j = 0; j < q->nb_buf_deps; j++)
1301  av_buffer_unref(&q->buf_deps[j]);
1302  av_free(q->buf_deps);
1303 
1304  /* Free frame dependencies */
1305  for (int j = 0; j < q->nb_frame_deps; j++)
1306  av_frame_free(&q->frame_deps[j]);
1307  av_free(q->frame_deps);
1308  }
1309 
1310  if (e->bufs)
1311  vk->FreeCommandBuffers(s->hwctx->act_dev, e->pool, e->qf->nb_queues, e->bufs);
1312  if (e->pool)
1313  vk->DestroyCommandPool(s->hwctx->act_dev, e->pool, s->hwctx->alloc);
1314 
1315  av_freep(&e->bufs);
1316  av_freep(&e->queues);
1317  av_freep(&e->sem_sig);
1318  av_freep(&e->sem_sig_val);
1320  av_freep(&e->sem_wait);
1321  av_freep(&e->sem_wait_dst);
1322  av_freep(&e->sem_wait_val);
1323  av_free(e);
1324 }
1325 
1327 {
1328  FFVulkanFunctions *vk = &s->vkfn;
1329 
1330  for (int i = 0; i < pl->shaders_num; i++) {
1331  FFVkSPIRVShader *shd = pl->shaders[i];
1332  av_bprint_finalize(&shd->src, NULL);
1333  vk->DestroyShaderModule(s->hwctx->act_dev, shd->shader.module,
1334  s->hwctx->alloc);
1335  av_free(shd);
1336  }
1337 
1338  vk->DestroyPipeline(s->hwctx->act_dev, pl->pipeline, s->hwctx->alloc);
1339  vk->DestroyPipelineLayout(s->hwctx->act_dev, pl->pipeline_layout,
1340  s->hwctx->alloc);
1341 
1342  for (int i = 0; i < pl->desc_layout_num; i++) {
1343  if (pl->desc_template && pl->desc_template[i])
1344  vk->DestroyDescriptorUpdateTemplate(s->hwctx->act_dev, pl->desc_template[i],
1345  s->hwctx->alloc);
1346  if (pl->desc_layout && pl->desc_layout[i])
1347  vk->DestroyDescriptorSetLayout(s->hwctx->act_dev, pl->desc_layout[i],
1348  s->hwctx->alloc);
1349  }
1350 
1351  /* Also frees the descriptor sets */
1352  if (pl->desc_pool)
1353  vk->DestroyDescriptorPool(s->hwctx->act_dev, pl->desc_pool,
1354  s->hwctx->alloc);
1355 
1356  av_freep(&pl->desc_staging);
1357  av_freep(&pl->desc_set);
1358  av_freep(&pl->shaders);
1359  av_freep(&pl->desc_layout);
1360  av_freep(&pl->desc_template);
1362  av_freep(&pl->push_consts);
1363  pl->push_consts_num = 0;
1364 
1365  /* Only freed in case of failure */
1366  av_freep(&pl->pool_size_desc);
1367  if (pl->desc_template_info) {
1368  for (int i = 0; i < pl->total_descriptor_sets; i += pl->qf->nb_queues) {
1369  VkDescriptorUpdateTemplateCreateInfo *dt = &pl->desc_template_info[i];
1370  av_free((void *)dt->pDescriptorUpdateEntries);
1371  }
1373  }
1374 
1375  av_free(pl);
1376 }
1377 
1379 {
1380  FFVulkanFunctions *vk = &s->vkfn;
1381 
1382  if (s->spirv_compiler)
1383  s->spirv_compiler->uninit(&s->spirv_compiler);
1384 
1385  for (int i = 0; i < s->exec_ctx_num; i++)
1386  free_exec_ctx(s, s->exec_ctx[i]);
1387  av_freep(&s->exec_ctx);
1388 
1389  for (int i = 0; i < s->samplers_num; i++) {
1390  vk->DestroySampler(s->hwctx->act_dev, s->samplers[i]->sampler[0],
1391  s->hwctx->alloc);
1392  av_free(s->samplers[i]);
1393  }
1394  av_freep(&s->samplers);
1395 
1396  for (int i = 0; i < s->pipelines_num; i++)
1397  free_pipeline(s, s->pipelines[i]);
1398  av_freep(&s->pipelines);
1399 
1400  av_freep(&s->scratch);
1401  s->scratch_size = 0;
1402 
1403  av_buffer_unref(&s->device_ref);
1404  av_buffer_unref(&s->frames_ref);
1405 }
FFVkExecContext::queues
FFVkQueueCtx * queues
Definition: vulkan.h:159
vulkan_loader.h
FFVulkanPipeline::bind_point
VkPipelineBindPoint bind_point
Definition: vulkan.h:107
AV_BPRINT_SIZE_UNLIMITED
#define AV_BPRINT_SIZE_UNLIMITED
AVPixelFormat
AVPixelFormat
Pixel format.
Definition: pixfmt.h:64
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
FFVkExecContext::sem_wait_dst_alloc
int sem_wait_dst_alloc
Definition: vulkan.h:175
FFVkExecContext::sem_wait
VkSemaphore * sem_wait
Definition: vulkan.h:167
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
vulkan_shaderc.c
FFVulkanPipeline::shaders_num
int shaders_num
Definition: vulkan.h:115
FFVkExecContext::qf
FFVkQueueFamilyCtx * qf
Definition: vulkan.h:155
ff_comp_identity_map
const VkComponentMapping ff_comp_identity_map
Definition: vulkan.c:51
av_bprint_finalize
int av_bprint_finalize(AVBPrint *buf, char **ret_str)
Finalize a print buffer.
Definition: bprint.c:234
av_bprint_init
void av_bprint_init(AVBPrint *buf, unsigned size_init, unsigned size_max)
Definition: bprint.c:68
ff_vk_create_buf
int ff_vk_create_buf(FFVulkanContext *s, FFVkBuffer *buf, size_t size, VkBufferUsageFlags usage, VkMemoryPropertyFlagBits flags)
Create a VkBuffer with the specified parameters.
Definition: vulkan.c:193
FFVulkanPipeline::pipeline_layout
VkPipelineLayout pipeline_layout
Definition: vulkan.h:110
av_pix_fmt_desc_get
const AVPixFmtDescriptor * av_pix_fmt_desc_get(enum AVPixelFormat pix_fmt)
Definition: pixdesc.c:2660
FFVkExecContext::sem_sig
VkSemaphore * sem_sig
Definition: vulkan.h:177
ff_vk_bind_pipeline_exec
void ff_vk_bind_pipeline_exec(FFVulkanContext *s, FFVkExecContext *e, FFVulkanPipeline *pl)
Add a command to bind the completed pipeline and its descriptor sets.
Definition: vulkan.c:1263
descriptor_props::is_uniform
int is_uniform
Definition: vulkan.c:904
av_frame_free
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
Definition: frame.c:109
AVFrame
This structure describes decoded (raw) audio or video data.
Definition: frame.h:317
index
fg index
Definition: ffmpeg_filter.c:167
data
const char data[16]
Definition: mxf.c:143
FFVkQueueCtx::buf_deps_alloc_size
int buf_deps_alloc_size
Definition: vulkan.h:146
ff_vk_compile_shader
int ff_vk_compile_shader(FFVulkanContext *s, FFVkSPIRVShader *shd, const char *entrypoint)
Compiles the shader, entrypoint must be set to "main".
Definition: vulkan.c:848
AV_LOG_VERBOSE
#define AV_LOG_VERBOSE
Detailed information.
Definition: log.h:196
fc
#define fc(width, name, range_min, range_max)
Definition: cbs_av1.c:551
AV_PIX_FMT_BGR24
@ AV_PIX_FMT_BGR24
packed RGB 8:8:8, 24bpp, BGRBGR...
Definition: pixfmt.h:69
AV_PIX_FMT_BGRA
@ AV_PIX_FMT_BGRA
packed BGRA 8:8:8:8, 32bpp, BGRABGRA...
Definition: pixfmt.h:95
ff_vk_uninit
void ff_vk_uninit(FFVulkanContext *s)
Frees the main Vulkan context.
Definition: vulkan.c:1378
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:157
FFMAX
#define FFMAX(a, b)
Definition: macros.h:47
FFVulkanPipeline::desc_pool
VkDescriptorPool desc_pool
Definition: vulkan.h:123
FFVulkanPipeline::desc_staging
void ** desc_staging
Definition: vulkan.h:125
FFVkExecContext::bound_pl
FFVulkanPipeline * bound_pl
Definition: vulkan.h:165
ImageViewCtx::view
VkImageView view
Definition: vulkan.c:729
FFVkSampler
Definition: vulkan.h:74
descriptor_props::type
const char * type
Definition: vulkan.c:903
FFVkBuffer::buf
VkBuffer buf
Definition: vulkan.h:92
av_malloc
#define av_malloc(s)
Definition: tableprint_vlc.h:31
ff_vk_add_exec_dep
int ff_vk_add_exec_dep(FFVulkanContext *s, FFVkExecContext *e, AVFrame *frame, VkPipelineStageFlagBits in_wait_dst_flag)
Adds a frame as a queue dependency.
Definition: vulkan.c:509
ImageViewCtx
Definition: vulkan.c:728
ff_vk_get_exec_buf
VkCommandBuffer ff_vk_get_exec_buf(FFVkExecContext *e)
Gets the command buffer to use for this submission from the exe context.
Definition: vulkan.c:504
av_pix_fmt_count_planes
int av_pix_fmt_count_planes(enum AVPixelFormat pix_fmt)
Definition: pixdesc.c:2700
ff_vk_print_shader
void ff_vk_print_shader(void *ctx, FFVkSPIRVShader *shd, int prio)
Pretty print shader, mainly used by shader compilers.
Definition: vulkan.c:827
ff_vk_add_push_constant
int ff_vk_add_push_constant(FFVulkanPipeline *pl, int offset, int size, VkShaderStageFlagBits stage)
Define a push constant for a given stage into a pipeline.
Definition: vulkan.c:364
FFVkExecContext::sem_wait_dst
VkPipelineStageFlagBits * sem_wait_dst
Definition: vulkan.h:174
FFVulkanPipeline::pipeline
VkPipeline pipeline
Definition: vulkan.h:111
FFVulkanPipeline::shaders
FFVkSPIRVShader ** shaders
Definition: vulkan.h:114
FFVkExecContext::sem_sig_val_dst_alloc
int sem_sig_val_dst_alloc
Definition: vulkan.h:185
cqueue_create
static cqueue * cqueue_create(int size, int max_size)
Definition: af_dynaudnorm.c:136
ff_vk_ret2str
const char * ff_vk_ret2str(VkResult res)
Converts Vulkan return values to strings.
Definition: vulkan.c:59
ff_vk_shaderc_init
static FFVkSPIRVCompiler * ff_vk_shaderc_init(void)
Definition: vulkan_shaderc.c:107
vk_alloc_mem
static int vk_alloc_mem(FFVulkanContext *s, VkMemoryRequirements *req, VkMemoryPropertyFlagBits req_flags, void *alloc_extension, VkMemoryPropertyFlagBits *mem_flags, VkDeviceMemory *mem)
Definition: vulkan.c:137
descriptor_props::struct_size
size_t struct_size
Definition: vulkan.c:902
ff_vk_qf_init
void ff_vk_qf_init(FFVulkanContext *s, FFVkQueueFamilyCtx *qf, VkQueueFlagBits dev_family, int nb_queues)
Initialize a queue family with a specific number of queues.
Definition: vulkan.c:96
FFVkQueueFamilyCtx::actual_queues
int actual_queues
Definition: vulkan.h:101
avassert.h
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:180
FFVkQueueCtx::queue
VkQueue queue
Definition: vulkan.h:141
ff_vk_create_imageview
int ff_vk_create_imageview(FFVulkanContext *s, FFVkExecContext *e, VkImageView *v, VkImage img, VkFormat fmt, const VkComponentMapping map)
Create an imageview.
Definition: vulkan.c:742
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:504
FFVkQueueCtx::frame_deps
AVFrame ** frame_deps
Definition: vulkan.h:149
s
#define s(width, name)
Definition: cbs_vp9.c:257
FFVkExecContext::sem_sig_alloc
int sem_sig_alloc
Definition: vulkan.h:178
av_realloc_array
void * av_realloc_array(void *ptr, size_t nmemb, size_t size)
Definition: mem.c:224
FFVulkanPipeline::desc_template
VkDescriptorUpdateTemplate * desc_template
Definition: vulkan.h:127
av_assert0
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition: avassert.h:37
ff_vk_init_shader
FFVkSPIRVShader * ff_vk_init_shader(FFVulkanPipeline *pl, const char *name, VkShaderStageFlags stage)
Inits a shader for a specific pipeline.
Definition: vulkan.c:795
ctx
AVFormatContext * ctx
Definition: movenc.c:48
av_frame_clone
AVFrame * av_frame_clone(const AVFrame *src)
Create a new frame that references the same data as src.
Definition: frame.c:422
pix_fmt
static enum AVPixelFormat pix_fmt
Definition: demuxing_decoding.c:41
FFVkExecContext::sem_sig_val
uint64_t * sem_sig_val
Definition: vulkan.h:181
f
#define f(width, name)
Definition: cbs_vp9.c:255
FFVulkanPipeline::desc_template_info
VkDescriptorUpdateTemplateCreateInfo * desc_template_info
Definition: vulkan.h:135
AV_PIX_FMT_RGBA
@ AV_PIX_FMT_RGBA
packed RGBA 8:8:8:8, 32bpp, RGBARGBA...
Definition: pixfmt.h:93
FFVkSampler::sampler
VkSampler sampler[4]
Definition: vulkan.h:75
ff_vk_update_descriptor_set
void ff_vk_update_descriptor_set(FFVulkanContext *s, FFVulkanPipeline *pl, int set_id)
Updates a descriptor set via the updaters defined.
Definition: vulkan.c:1079
planes
static const struct @321 planes[]
ff_vk_start_exec_recording
int ff_vk_start_exec_recording(FFVulkanContext *s, FFVkExecContext *e)
Begin recording to the command buffer.
Definition: vulkan.c:463
free_pipeline
static void free_pipeline(FFVulkanContext *s, FFVulkanPipeline *pl)
Definition: vulkan.c:1326
destroy_imageview
static void destroy_imageview(void *opaque, uint8_t *data)
Definition: vulkan.c:732
AV_PIX_FMT_RGBA64
#define AV_PIX_FMT_RGBA64
Definition: pixfmt.h:394
descriptor_props::mem_quali
int mem_quali
Definition: vulkan.c:905
FFVkQueueCtx
Definition: vulkan.h:139
flush
static void flush(AVCodecContext *avctx)
Definition: aacdec_template.c:593
NULL
#define NULL
Definition: coverity.c:32
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
FFVkExecContext::sem_wait_alloc
int sem_wait_alloc
Definition: vulkan.h:168
FFVkExecContext::sem_sig_cnt
int sem_sig_cnt
Definition: vulkan.h:179
ff_vk_update_push_exec
void ff_vk_update_push_exec(FFVulkanContext *s, FFVkExecContext *e, VkShaderStageFlagBits stage, int offset, size_t size, void *src)
Updates push constants.
Definition: vulkan.c:1105
ff_vk_create_exec_ctx
int ff_vk_create_exec_ctx(FFVulkanContext *s, FFVkExecContext **ctx, FFVkQueueFamilyCtx *qf)
Init an execution context for command recording and queue submission.
Definition: vulkan.c:385
src
#define src
Definition: vp8dsp.c:255
ff_vk_qf_rotate
void ff_vk_qf_rotate(FFVkQueueFamilyCtx *qf)
Rotate through the queues in a queue family.
Definition: vulkan.c:132
descriptor_props::dim_needed
int dim_needed
Definition: vulkan.c:906
AV_PIX_FMT_BGR0
@ AV_PIX_FMT_BGR0
packed BGR 8:8:8, 32bpp, BGRXBGRX... X=unused/undefined
Definition: pixfmt.h:230
FFVkExecContext::sem_sig_val_alloc
int sem_sig_val_alloc
Definition: vulkan.h:182
FFVulkanContext
Definition: vulkan.h:188
AV_PIX_FMT_ABGR
@ AV_PIX_FMT_ABGR
packed ABGR 8:8:8:8, 32bpp, ABGRABGR...
Definition: pixfmt.h:94
FFVulkanPipeline
Definition: vulkan.h:104
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
ff_vk_discard_exec_deps
void ff_vk_discard_exec_deps(FFVkExecContext *e)
Discards all queue dependencies.
Definition: vulkan.c:447
usage
const char * usage
Definition: floatimg_cmp.c:60
ff_vk_unmap_buffers
int ff_vk_unmap_buffers(FFVulkanContext *s, FFVkBuffer *buf, int nb_buffers, int flush)
Unmaps the buffer from userspace.
Definition: vulkan.c:307
FFVkQueueCtx::fence
VkFence fence
Definition: vulkan.h:140
FFVulkanPipeline::desc_layout_num
int desc_layout_num
Definition: vulkan.h:129
FFVkExecContext::pool
VkCommandPool pool
Definition: vulkan.h:157
AV_PIX_FMT_RGB24
@ AV_PIX_FMT_RGB24
packed RGB 8:8:8, 24bpp, RGBRGB...
Definition: pixfmt.h:68
FFVulkanPipeline::total_descriptor_sets
int total_descriptor_sets
Definition: vulkan.h:131
FFVulkanDescriptorSetBinding
Definition: vulkan.h:78
AVVkFrame
Definition: hwcontext_vulkan.h:213
print
static void print(AVTreeNode *t, int depth)
Definition: tree.c:44
AV_PIX_FMT_RGB48
#define AV_PIX_FMT_RGB48
Definition: pixfmt.h:390
ff_vk_init_pipeline_layout
int ff_vk_init_pipeline_layout(FFVulkanContext *s, FFVulkanPipeline *pl)
Initializes the pipeline layout after all shaders and descriptor sets have been finished.
Definition: vulkan.c:1115
size
int size
Definition: twinvq_data.h:10344
FFVkQueueFamilyCtx
Definition: vulkan.h:97
FN_CREATING
#define FN_CREATING(ctx, type, shortname, array, num)
Definition: vulkan.c:32
FFVkBuffer::flags
VkMemoryPropertyFlagBits flags
Definition: vulkan.h:94
img
#define img
Definition: vf_colormatrix.c:116
ff_vk_submit_exec_queue
int ff_vk_submit_exec_queue(FFVulkanContext *s, FFVkExecContext *e)
Submits a command buffer to the queue for execution.
Definition: vulkan.c:590
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:154
line
Definition: graph2dot.c:48
AV_PIX_FMT_RGB0
@ AV_PIX_FMT_RGB0
packed RGB 8:8:8, 32bpp, RGBXRGBX... X=unused/undefined
Definition: pixfmt.h:228
FFVulkanPipeline::desc_set
VkDescriptorSet * desc_set
Definition: vulkan.h:124
version
version
Definition: libkvazaar.c:313
ff_vk_mt_is_np_rgb
int ff_vk_mt_is_np_rgb(enum AVPixelFormat pix_fmt)
Returns 1 if the image is any sort of supported RGB.
Definition: vulkan.c:709
create_exec_ctx
static int create_exec_ctx(AVHWFramesContext *hwfc, VulkanExecCtx *cmd, int queue_family_index, int num_queues)
Definition: hwcontext_vulkan.c:1064
FFVkExecContext::sem_wait_cnt
int sem_wait_cnt
Definition: vulkan.h:169
FFVkQueueCtx::nb_buf_deps
int nb_buf_deps
Definition: vulkan.h:145
vulkan.h
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
ff_vk_add_dep_exec_ctx
int ff_vk_add_dep_exec_ctx(FFVulkanContext *s, FFVkExecContext *e, AVBufferRef **deps, int nb_deps)
Adds a generic AVBufferRef as a queue depenency.
Definition: vulkan.c:639
descriptor_props
Definition: vulkan.c:901
ff_vk_init_compute_pipeline
int ff_vk_init_compute_pipeline(FFVulkanContext *s, FFVulkanPipeline *pl)
Initializes a compute pipeline.
Definition: vulkan.c:1228
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:271
FFVulkanPipeline::pool_size_desc
VkDescriptorPoolSize * pool_size_desc
Definition: vulkan.h:136
FFVulkanPipeline::push_consts
VkPushConstantRange * push_consts
Definition: vulkan.h:118
FFVkSPIRVShader::shader
VkPipelineShaderStageCreateInfo shader
Definition: vulkan.h:62
FFVulkanPipeline::qf
FFVkQueueFamilyCtx * qf
Definition: vulkan.h:105
ff_vk_shader_rep_fmt
const char * ff_vk_shader_rep_fmt(enum AVPixelFormat pixfmt)
Gets the glsl format string for a pixel format.
Definition: vulkan.c:721
FFVkBuffer::mem
VkDeviceMemory mem
Definition: vulkan.h:93
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:263
FFVkSPIRVShader::src
AVBPrint src
Definition: vulkan.h:60
AV_PIX_FMT_BGR565
#define AV_PIX_FMT_BGR565
Definition: pixfmt.h:396
filt
static const int8_t filt[NUMTAPS *2]
Definition: af_earwax.c:39
GLSLF
#define GLSLF(N, S,...)
Definition: vulkan.h:46
ff_vk_create_pipeline
FFVulkanPipeline * ff_vk_create_pipeline(FFVulkanContext *s, FFVkQueueFamilyCtx *qf)
Inits a pipeline.
Definition: vulkan.c:1219
ff_vk_free_buf
void ff_vk_free_buf(FFVulkanContext *s, FFVkBuffer *buf)
Frees a buffer.
Definition: vulkan.c:349
AV_PIX_FMT_RGB565
#define AV_PIX_FMT_RGB565
Definition: pixfmt.h:391
AVHWFramesContext
This struct describes a set or pool of "hardware" frames (i.e.
Definition: hwcontext.h:124
FFVulkanPipeline::desc_set_initialized
int * desc_set_initialized
Definition: vulkan.h:128
FFVulkanPipeline::push_consts_num
int push_consts_num
Definition: vulkan.h:119
ret
ret
Definition: filter_design.txt:187
pixfmt
enum AVPixelFormat pixfmt
Definition: kmsgrab.c:365
AV_PIX_FMT_0BGR
@ AV_PIX_FMT_0BGR
packed BGR 8:8:8, 32bpp, XBGRXBGR... X=unused/undefined
Definition: pixfmt.h:229
frame
these buffered frames must be flushed immediately if a new input produces new the filter must not call request_frame to get more It must just process the frame or queue it The task of requesting more frames is left to the filter s request_frame method or the application If a filter has several the filter must be ready for frames arriving randomly on any input any filter with several inputs will most likely require some kind of queuing mechanism It is perfectly acceptable to have a limited queue and to drop frames when the inputs are too unbalanced request_frame For filters that do not use the this method is called when a frame is wanted on an output For a it should directly call filter_frame on the corresponding output For a if there are queued frames already one of these frames should be pushed If the filter should request a frame on one of its repeatedly until at least one frame has been pushed Return or at least make progress towards producing a frame
Definition: filter_design.txt:264
descriptor_props::buf_content
int buf_content
Definition: vulkan.c:907
av_bprintf
void av_bprintf(AVBPrint *buf, const char *fmt,...)
Definition: bprint.c:93
GLSLA
#define GLSLA(...)
Definition: vulkan.h:45
ff_vk_add_descriptor_set
int ff_vk_add_descriptor_set(FFVulkanContext *s, FFVulkanPipeline *pl, FFVkSPIRVShader *shd, FFVulkanDescriptorSetBinding *desc, int num, int only_print_to_shader)
Adds a descriptor set to the shader and registers them in the pipeline.
Definition: vulkan.c:922
FFVkQueueFamilyCtx::nb_queues
int nb_queues
Definition: vulkan.h:99
FFVkQueueFamilyCtx::cur_queue
int cur_queue
Definition: vulkan.h:100
FFVkSPIRVShader
Definition: vulkan.h:58
vulkan_glslang.c
ff_vk_init_sampler
FFVkSampler * ff_vk_init_sampler(FFVulkanContext *s, int unnorm_coords, VkFilter filt)
Create a Vulkan sampler, will be auto-freed in ff_vk_filter_uninit()
Definition: vulkan.c:670
desc
const char * desc
Definition: libsvtav1.c:79
GLSLC
#define GLSLC(N, S)
Definition: vulkan.h:44
FFVulkanPipeline::descriptor_sets_num
int descriptor_sets_num
Definition: vulkan.h:130
AVBufferRef
A reference to a data buffer.
Definition: buffer.h:82
FFVkExecContext::bufs
VkCommandBuffer * bufs
Definition: vulkan.h:158
FFVkSPIRVShader::name
const char * name
Definition: vulkan.h:59
ff_vk_map_buffers
int ff_vk_map_buffers(FFVulkanContext *s, FFVkBuffer *buf, uint8_t *mem[], int nb_buffers, int invalidate)
Maps the buffer to userspace.
Definition: vulkan.c:258
AVPixFmtDescriptor
Descriptor that unambiguously describes how the bits of a pixel are stored in the up to 4 data planes...
Definition: pixdesc.h:69
map
const VDPAUPixFmtMap * map
Definition: hwcontext_vdpau.c:71
av_free
#define av_free(p)
Definition: tableprint_vlc.h:34
FFVkSPIRVShader::local_size
int local_size[3]
Definition: vulkan.h:61
FFALIGN
#define FFALIGN(x, a)
Definition: macros.h:78
av_freep
#define av_freep(p)
Definition: tableprint_vlc.h:35
ff_vk_set_compute_shader_sizes
void ff_vk_set_compute_shader_sizes(FFVkSPIRVShader *shd, int local_size[3])
Writes the workgroup size for a shader.
Definition: vulkan.c:816
FFVkBuffer
Definition: vulkan.h:91
FFVkExecContext::sem_wait_val
uint64_t * sem_wait_val
Definition: vulkan.h:171
flags
#define flags(name, subs,...)
Definition: cbs_av1.c:561
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:28
FFVulkanPipeline::pool_size_desc_num
int pool_size_desc_num
Definition: vulkan.h:132
FFVkQueueCtx::nb_frame_deps
int nb_frame_deps
Definition: vulkan.h:150
free_exec_ctx
static void free_exec_ctx(FFVulkanContext *s, FFVkExecContext *e)
Definition: vulkan.c:1282
FFVkExecContext::sem_sig_val_dst
uint64_t ** sem_sig_val_dst
Definition: vulkan.h:184
int
int
Definition: ffmpeg_filter.c:153
FFVkExecContext::sem_wait_val_alloc
int sem_wait_val_alloc
Definition: vulkan.h:172
CASE
#define CASE(VAL)
FFVkQueueCtx::buf_deps
AVBufferRef ** buf_deps
Definition: vulkan.h:144
FFVulkanPipeline::desc_layout
VkDescriptorSetLayout * desc_layout
Definition: vulkan.h:122
FFVulkanFunctions
Definition: vulkan_functions.h:175
ff_vk_glslang_init
static FFVkSPIRVCompiler * ff_vk_glslang_init(void)
Definition: vulkan_glslang.c:260
FFVkQueueFamilyCtx::queue_family
int queue_family
Definition: vulkan.h:98