FFmpeg
vulkan_ffv1.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2024 Lynne <dev@lynne.ee>
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 "vulkan_decode.h"
22 #include "hwaccel_internal.h"
23 
24 #include "ffv1.h"
25 #include "ffv1_vulkan.h"
26 #include "libavutil/mem.h"
27 
28 #define RGB_LINECACHE 2
29 
30 extern const unsigned char ff_ffv1_dec_setup_comp_spv_data[];
31 extern const unsigned int ff_ffv1_dec_setup_comp_spv_len;
32 
33 extern const unsigned char ff_ffv1_dec_reset_comp_spv_data[];
34 extern const unsigned int ff_ffv1_dec_reset_comp_spv_len;
35 
36 extern const unsigned char ff_ffv1_dec_reset_golomb_comp_spv_data[];
37 extern const unsigned int ff_ffv1_dec_reset_golomb_comp_spv_len;
38 
39 extern const unsigned char ff_ffv1_dec_comp_spv_data[];
40 extern const unsigned int ff_ffv1_dec_comp_spv_len;
41 
42 extern const unsigned char ff_ffv1_dec_rgb_comp_spv_data[];
43 extern const unsigned int ff_ffv1_dec_rgb_comp_spv_len;
44 
45 extern const unsigned char ff_ffv1_dec_golomb_comp_spv_data[];
46 extern const unsigned int ff_ffv1_dec_golomb_comp_spv_len;
47 
48 extern const unsigned char ff_ffv1_dec_rgb_golomb_comp_spv_data[];
49 extern const unsigned int ff_ffv1_dec_rgb_golomb_comp_spv_len;
50 
51 extern const unsigned char ff_ffv1_dec_rgb_float_comp_spv_data[];
52 extern const unsigned int ff_ffv1_dec_rgb_float_comp_spv_len;
53 
54 extern const unsigned char ff_ffv1_dec_rgb_float_golomb_comp_spv_data[];
55 extern const unsigned int ff_ffv1_dec_rgb_float_golomb_comp_spv_len;
56 
57 extern const unsigned char ff_ffv1_dec_bayer_comp_spv_data[];
58 extern const unsigned int ff_ffv1_dec_bayer_comp_spv_len;
59 
60 extern const unsigned char ff_ffv1_dec_bayer_golomb_comp_spv_data[];
61 extern const unsigned int ff_ffv1_dec_bayer_golomb_comp_spv_len;
62 
65  .queue_flags = VK_QUEUE_COMPUTE_BIT,
66 };
67 
68 typedef struct FFv1VulkanDecodePicture {
70 
72  uint32_t plane_state_size;
73  uint32_t slice_state_size;
74  uint32_t slice_data_size;
75 
78  uint32_t *slice_offset;
79  int slice_num;
82 
83 typedef struct FFv1VulkanDecodeContext {
85 
89 
91 
96 
98  const AVBufferRef *buffer_ref,
99  av_unused const uint8_t *buffer,
100  av_unused uint32_t size)
101 {
102  int err;
105  FFv1VulkanDecodeContext *fv = ctx->sd_ctx;
106  FFV1Context *f = avctx->priv_data;
107 
108  FFv1VulkanDecodePicture *fp = f->hwaccel_picture_private;
109  FFVulkanDecodePicture *vp = &fp->vp;
110 
112  enum AVPixelFormat sw_format = hwfc->sw_format;
113 
114  int max_contexts;
115  int is_rgb = !(f->colorspace == 0 && sw_format != AV_PIX_FMT_YA8) &&
116  !(sw_format == AV_PIX_FMT_YA8);
117 
118  fp->slice_num = 0;
119 
120  max_contexts = 0;
121  for (int i = 0; i < f->quant_table_count; i++)
122  max_contexts = FFMAX(f->context_count[i], max_contexts);
123 
124  /* Allocate slice buffer data */
125  if (f->ac == AC_GOLOMB_RICE)
126  fp->plane_state_size = 8;
127  else
129 
130  fp->plane_state_size *= max_contexts;
131  fp->slice_state_size = fp->plane_state_size*f->plane_count;
132 
133  fp->slice_data_size = 256; /* Overestimation for the SliceContext struct */
136 
137  fp->crc_checked = f->ec && (avctx->err_recognition & AV_EF_CRCCHECK);
138 
139  /* Host map the input slices data if supported */
140  if (ctx->s.extensions & FF_VK_EXT_EXTERNAL_HOST_MEMORY)
141  ff_vk_host_map_buffer(&ctx->s, &vp->slices_buf, buffer_ref->data,
142  buffer_ref,
143  VK_BUFFER_USAGE_STORAGE_BUFFER_BIT |
144  VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT);
145 
146  /* Allocate slice state data */
147  if (f->picture.f->flags & AV_FRAME_FLAG_KEY) {
149  &fp->slice_state,
150  VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,
151  NULL, f->slice_count*fp->slice_state_size,
152  VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
153  if (err < 0)
154  return err;
155  } else {
156  FFv1VulkanDecodePicture *fpl = f->hwaccel_last_picture_private;
158  if (!fp->slice_state)
159  return AVERROR(ENOMEM);
160  }
161 
162  /* Allocate slice offsets/status buffer */
164  &fp->slice_feedback_buf,
165  VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,
166  NULL, 2*(2*f->slice_count*sizeof(uint32_t)),
167  VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT |
168  VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT);
169  if (err < 0)
170  return err;
171 
172  /* Allocate slice offsets/status buffer (note, for integer+remap, we don't need it) */
173  if (f->version >=4 && f->micro_version >= 9 &&
176  &fp->slice_fltmap_buf,
177  VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,
178  NULL, 65536*4*f->slice_count*sizeof(uint32_t),
179  VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT |
180  VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT);
181  if (err < 0)
182  return err;
183  }
184 
185  /* Prepare frame to be used */
186  err = ff_vk_decode_prepare_frame_sdr(dec, f->picture.f, vp, 1,
187  FF_VK_REP_NATIVE, 0);
188  if (err < 0)
189  return err;
190 
191  /* Create a temporaty frame for RGB */
192  if (is_rgb) {
193  vp->dpb_frame = av_frame_alloc();
194  if (!vp->dpb_frame)
195  return AVERROR(ENOMEM);
196 
198  vp->dpb_frame, 0);
199  if (err < 0)
200  return err;
201  }
202 
203  return 0;
204 }
205 
207  const uint8_t *data,
208  uint32_t size)
209 {
210  FFV1Context *f = avctx->priv_data;
211 
212  FFv1VulkanDecodePicture *fp = f->hwaccel_picture_private;
213  FFVulkanDecodePicture *vp = &fp->vp;
214 
215  FFVkBuffer *slice_offset = (FFVkBuffer *)fp->slice_feedback_buf->data;
216  FFVkBuffer *slices_buf = vp->slices_buf ? (FFVkBuffer *)vp->slices_buf->data : NULL;
217 
218  if (slices_buf && slices_buf->host_ref) {
219  AV_WN32(slice_offset->mapped_mem + (2*fp->slice_num + 0)*sizeof(uint32_t),
220  data - slices_buf->mapped_mem);
221  AV_WN32(slice_offset->mapped_mem + (2*fp->slice_num + 1)*sizeof(uint32_t),
222  size);
223 
224  fp->slice_num++;
225  } else {
226  int err = ff_vk_decode_add_slice(avctx, vp, data, size, 0,
227  &fp->slice_num,
228  (const uint32_t **)&fp->slice_offset);
229  if (err < 0)
230  return err;
231 
232  AV_WN32(slice_offset->mapped_mem + (2*(fp->slice_num - 1) + 0)*sizeof(uint32_t),
233  fp->slice_offset[fp->slice_num - 1]);
234  AV_WN32(slice_offset->mapped_mem + (2*(fp->slice_num - 1) + 1)*sizeof(uint32_t),
235  size);
236  }
237 
238  return 0;
239 }
240 
242 {
243  int err;
246  FFVulkanFunctions *vk = &ctx->s.vkfn;
247 
248  FFV1Context *f = avctx->priv_data;
249  FFv1VulkanDecodeContext *fv = ctx->sd_ctx;
250 
252  enum AVPixelFormat sw_format = hwfc->sw_format;
253 
254  int is_rgb = !(f->colorspace == 0 && sw_format != AV_PIX_FMT_YA8) &&
255  !(sw_format == AV_PIX_FMT_YA8);
256  int color_planes = av_pix_fmt_desc_get(avctx->sw_pix_fmt)->nb_components;
257 
258  FFv1VulkanDecodePicture *fp = f->hwaccel_picture_private;
259  FFVulkanDecodePicture *vp = &fp->vp;
260 
261  FFVkBuffer *slices_buf = (FFVkBuffer *)vp->slices_buf->data;
262  FFVkBuffer *slice_state = (FFVkBuffer *)fp->slice_state->data;
263  FFVkBuffer *slice_feedback = (FFVkBuffer *)fp->slice_feedback_buf->data;
264  FFVkBuffer *fltmap_buf = NULL;
265  if (fp->slice_fltmap_buf)
266  fltmap_buf = (FFVkBuffer *)fp->slice_fltmap_buf->data;
267 
268  VkImageView rct_image_views[AV_NUM_DATA_POINTERS];
269 
270  VkImageMemoryBarrier2 img_bar[37];
271  int nb_img_bar = 0;
272  VkBufferMemoryBarrier2 buf_bar[8];
273  int nb_buf_bar = 0;
274 
275  FFVkExecContext *exec = ff_vk_exec_get(&ctx->s, &ctx->exec_pool);
276  ff_vk_exec_start(&ctx->s, exec);
277 
278  /* Prepare deps */
279  RET(ff_vk_exec_add_dep_frame(&ctx->s, exec, f->picture.f,
280  VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
281  VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT));
282 
283  err = ff_vk_exec_mirror_sem_value(&ctx->s, exec, &vp->sem, &vp->sem_value,
284  f->picture.f);
285  if (err < 0)
286  return err;
287 
288  if (is_rgb) {
289  RET(ff_vk_create_imageviews(&ctx->s, exec, rct_image_views,
291  RET(ff_vk_exec_add_dep_frame(&ctx->s, exec, vp->dpb_frame,
292  VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
293  VK_PIPELINE_STAGE_2_CLEAR_BIT));
294  }
295 
296  if (!(f->picture.f->flags & AV_FRAME_FLAG_KEY)) {
297  FFv1VulkanDecodePicture *fpl = f->hwaccel_last_picture_private;
298  FFVulkanDecodePicture *vpl = &fpl->vp;
299 
300  /* Wait on the previous frame */
301  RET(ff_vk_exec_add_dep_wait_sem(&ctx->s, exec, vpl->sem, vpl->sem_value,
302  VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT));
303  }
304 
305  RET(ff_vk_exec_add_dep_buf(&ctx->s, exec, &fp->slice_state, 1, 1));
306  RET(ff_vk_exec_add_dep_buf(&ctx->s, exec, &fp->slice_feedback_buf, 1, 1));
307  RET(ff_vk_exec_add_dep_buf(&ctx->s, exec, &vp->slices_buf, 1, 0));
308  vp->slices_buf = NULL;
309 
310  if (fp->slice_fltmap_buf) {
311  RET(ff_vk_exec_add_dep_buf(&ctx->s, exec, &fp->slice_fltmap_buf, 1, 0));
312  fp->slice_fltmap_buf = NULL;
313  }
314 
315  AVVkFrame *vkf = (AVVkFrame *)f->picture.f->data[0];
316  for (int i = 0; i < ff_vk_count_images(vkf); i++) {
317  vkf->layout[i] = VK_IMAGE_LAYOUT_UNDEFINED;
318  vkf->access[i] = VK_ACCESS_2_NONE;
319  }
320 
321  /* Setup shader */
322  ff_vk_shader_update_desc_buffer(&ctx->s, exec, &fv->setup,
323  1, 0, 0,
324  slice_state,
325  0, fp->slice_data_size*f->slice_count,
326  VK_FORMAT_UNDEFINED);
327  ff_vk_shader_update_desc_buffer(&ctx->s, exec, &fv->setup,
328  1, 1, 0,
329  slice_feedback,
330  0, 2*f->slice_count*sizeof(uint32_t),
331  VK_FORMAT_UNDEFINED);
332  ff_vk_shader_update_desc_buffer(&ctx->s, exec, &fv->setup,
333  1, 2, 0,
334  slice_feedback,
335  2*f->slice_count*sizeof(uint32_t),
336  VK_WHOLE_SIZE,
337  VK_FORMAT_UNDEFINED);
338  if (fltmap_buf)
339  ff_vk_shader_update_desc_buffer(&ctx->s, exec, &fv->setup,
340  1, 3, 0,
341  fltmap_buf,
342  0,
343  VK_WHOLE_SIZE,
344  VK_FORMAT_UNDEFINED);
345 
346  ff_vk_exec_bind_shader(&ctx->s, exec, &fv->setup);
347 
348  FFv1ShaderParams pd = {
349  .slice_data = slices_buf->address,
350 
351  .img_size[0] = f->picture.f->width,
352  .img_size[1] = f->picture.f->height,
353 
354  .plane_state_size = fp->plane_state_size,
355  .key_frame = f->picture.f->flags & AV_FRAME_FLAG_KEY,
356  .crcref = f->crcref,
357  .micro_version = f->micro_version,
358  };
359 
360  for (int i = 0; i < f->quant_table_count; i++) {
361  pd.context_count[i] = f->context_count[i];
362  pd.extend_lookup[i] = f->quant_tables[i][3][127] ||
363  f->quant_tables[i][4][127];
364  }
365 
366  /* For some reason the C FFv1 encoder/decoder treats these differently */
367  if (sw_format == AV_PIX_FMT_GBRP10 || sw_format == AV_PIX_FMT_GBRP12 ||
368  sw_format == AV_PIX_FMT_GBRP14)
369  memcpy(pd.fmt_lut, (int [4]) { 2, 1, 0, 3 }, 4*sizeof(int));
370  else
371  ff_vk_set_perm(sw_format, pd.fmt_lut, 0);
372 
373  ff_vk_shader_update_push_const(&ctx->s, exec, &fv->setup,
374  VK_SHADER_STAGE_COMPUTE_BIT,
375  0, sizeof(FFv1ShaderParams), &pd);
376 
377  vk->CmdDispatch(exec->buf, f->num_h_slices, f->num_v_slices, 1);
378 
379  if (is_rgb) {
380  vkf = (AVVkFrame *)vp->dpb_frame->data[0];
381  for (int i = 0; i < 4; i++) {
382  vkf->layout[i] = VK_IMAGE_LAYOUT_UNDEFINED;
383  vkf->access[i] = VK_ACCESS_2_NONE;
384  }
385 
386  ff_vk_frame_barrier(&ctx->s, exec, vp->dpb_frame, img_bar, &nb_img_bar,
387  VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
388  VK_PIPELINE_STAGE_2_CLEAR_BIT,
389  VK_ACCESS_2_TRANSFER_WRITE_BIT,
390  VK_IMAGE_LAYOUT_GENERAL,
391  VK_QUEUE_FAMILY_IGNORED);
392 
393  vk->CmdPipelineBarrier2(exec->buf, &(VkDependencyInfo) {
394  .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
395  .pImageMemoryBarriers = img_bar,
396  .imageMemoryBarrierCount = nb_img_bar,
397  .pBufferMemoryBarriers = buf_bar,
398  .bufferMemoryBarrierCount = nb_buf_bar,
399  });
400  nb_img_bar = 0;
401  nb_buf_bar = 0;
402 
403  /* The intermediate frame has 4 planes (GBRAP16/32). Clear all of
404  * them since the bayer decoder uses all four. */
405  int n_dec_planes = f->bayer ? 4 : color_planes;
406  for (int i = 0; i < n_dec_planes; i++)
407  vk->CmdClearColorImage(exec->buf, vkf->img[i], VK_IMAGE_LAYOUT_GENERAL,
408  &((VkClearColorValue) { 0 }),
409  1, &((VkImageSubresourceRange) {
410  .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
411  .levelCount = 1,
412  .layerCount = 1,
413  }));
414  }
415 
416  /* Sync between setup and reset shaders */
417  ff_vk_buf_barrier(buf_bar[nb_buf_bar++], slice_state,
418  COMPUTE_SHADER_BIT, SHADER_STORAGE_READ_BIT,
419  SHADER_STORAGE_WRITE_BIT,
420  COMPUTE_SHADER_BIT, SHADER_STORAGE_READ_BIT, NONE_KHR,
421  0, fp->slice_data_size*f->slice_count);
422 
423  /* Probability data barrier for P-frames */
424  if (!(f->picture.f->flags & AV_FRAME_FLAG_KEY))
425  ff_vk_buf_barrier(buf_bar[nb_buf_bar++], slice_state,
426  COMPUTE_SHADER_BIT, SHADER_STORAGE_READ_BIT,
427  SHADER_STORAGE_WRITE_BIT,
428  COMPUTE_SHADER_BIT, SHADER_STORAGE_WRITE_BIT, NONE_KHR,
429  fp->slice_data_size*f->slice_count, VK_WHOLE_SIZE);
430 
431  vk->CmdPipelineBarrier2(exec->buf, &(VkDependencyInfo) {
432  .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
433  .pImageMemoryBarriers = img_bar,
434  .imageMemoryBarrierCount = nb_img_bar,
435  .pBufferMemoryBarriers = buf_bar,
436  .bufferMemoryBarrierCount = nb_buf_bar,
437  });
438  nb_buf_bar = 0;
439  nb_img_bar = 0;
440 
441  /* Reset shader */
442  ff_vk_shader_update_desc_buffer(&ctx->s, exec, &fv->reset,
443  1, 0, 0,
444  slice_state,
445  0, fp->slice_data_size*f->slice_count,
446  VK_FORMAT_UNDEFINED);
447  ff_vk_shader_update_desc_buffer(&ctx->s, exec, &fv->reset,
448  1, 1, 0,
449  slice_state,
450  f->slice_count*fp->slice_data_size,
451  VK_WHOLE_SIZE,
452  VK_FORMAT_UNDEFINED);
453 
454  ff_vk_exec_bind_shader(&ctx->s, exec, &fv->reset);
455  ff_vk_shader_update_push_const(&ctx->s, exec, &fv->reset,
456  VK_SHADER_STAGE_COMPUTE_BIT,
457  0, sizeof(FFv1ShaderParams), &pd);
458 
459  vk->CmdDispatch(exec->buf, f->num_h_slices, f->num_v_slices,
460  f->plane_count);
461 
462  /* Sync probabilities between reset and decode shaders */
463  ff_vk_buf_barrier(buf_bar[nb_buf_bar++], slice_state,
464  COMPUTE_SHADER_BIT, SHADER_STORAGE_WRITE_BIT, NONE_KHR,
465  COMPUTE_SHADER_BIT, SHADER_STORAGE_READ_BIT,
466  SHADER_STORAGE_WRITE_BIT,
467  fp->slice_data_size*f->slice_count, VK_WHOLE_SIZE);
468 
469  /* Input frame barrier */
470  ff_vk_frame_barrier(&ctx->s, exec, f->picture.f, img_bar, &nb_img_bar,
471  VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
472  VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT,
473  VK_ACCESS_SHADER_WRITE_BIT |
474  (!is_rgb ? VK_ACCESS_SHADER_READ_BIT : 0),
475  VK_IMAGE_LAYOUT_GENERAL,
476  VK_QUEUE_FAMILY_IGNORED);
477  if (is_rgb)
478  ff_vk_frame_barrier(&ctx->s, exec, vp->dpb_frame, img_bar, &nb_img_bar,
479  VK_PIPELINE_STAGE_2_CLEAR_BIT,
480  VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT,
481  VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT,
482  VK_IMAGE_LAYOUT_GENERAL,
483  VK_QUEUE_FAMILY_IGNORED);
484 
485  vk->CmdPipelineBarrier2(exec->buf, &(VkDependencyInfo) {
486  .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
487  .pImageMemoryBarriers = img_bar,
488  .imageMemoryBarrierCount = nb_img_bar,
489  .pBufferMemoryBarriers = buf_bar,
490  .bufferMemoryBarrierCount = nb_buf_bar,
491  });
492  nb_img_bar = 0;
493  nb_buf_bar = 0;
494 
495  /* Decode */
497  1, 0, 0,
498  slice_state,
499  0, fp->slice_data_size*f->slice_count,
500  VK_FORMAT_UNDEFINED);
502  1, 1, 0,
503  slice_feedback,
504  0, 2*f->slice_count*sizeof(uint32_t),
505  VK_FORMAT_UNDEFINED);
507  1, 2, 0,
508  slice_feedback,
509  2*f->slice_count*sizeof(uint32_t),
510  VK_WHOLE_SIZE,
511  VK_FORMAT_UNDEFINED);
513  1, 3, 0,
514  slice_state,
515  f->slice_count*fp->slice_data_size,
516  VK_WHOLE_SIZE,
517  VK_FORMAT_UNDEFINED);
518 
519  AVFrame *decode_dst = is_rgb ? vp->dpb_frame : f->picture.f;
520  VkImageView *decode_dst_view = is_rgb ? rct_image_views : vp->view.out;
521  ff_vk_shader_update_img_array(&ctx->s, exec, &fv->decode,
522  decode_dst, decode_dst_view,
523  1, 4,
524  VK_IMAGE_LAYOUT_GENERAL,
525  VK_NULL_HANDLE);
526  if (is_rgb)
527  ff_vk_shader_update_img_array(&ctx->s, exec, &fv->decode,
528  f->picture.f, vp->view.out,
529  1, 5,
530  VK_IMAGE_LAYOUT_GENERAL,
531  VK_NULL_HANDLE);
532  if (fltmap_buf)
534  1, 6, 0,
535  fltmap_buf,
536  0,
537  VK_WHOLE_SIZE,
538  VK_FORMAT_UNDEFINED);
539 
540  ff_vk_exec_bind_shader(&ctx->s, exec, &fv->decode);
541  ff_vk_shader_update_push_const(&ctx->s, exec, &fv->decode,
542  VK_SHADER_STAGE_COMPUTE_BIT,
543  0, sizeof(FFv1ShaderParams), &pd);
544 
545  vk->CmdDispatch(exec->buf, f->num_h_slices, f->num_v_slices, 1);
546 
547  err = ff_vk_exec_submit(&ctx->s, exec);
548  if (err < 0)
549  return err;
550 
551  /* We don't need the temporary frame after decoding */
552  av_frame_free(&vp->dpb_frame);
553 
554 fail:
555  return 0;
556 }
557 
559  FFVkExecPool *pool, FFVulkanShader *shd,
560  VkSpecializationInfo *sl)
561 {
562  int err;
563 
564  ff_vk_shader_load(shd, VK_SHADER_STAGE_COMPUTE_BIT, sl,
565  (uint32_t []) { 1, 1, 1 }, 0);
566 
568  VK_SHADER_STAGE_COMPUTE_BIT);
569 
570  const FFVulkanDescriptorSetBinding desc_set_const[] = {
571  { /* rangecoder_buf */
572  .type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
573  .stages = VK_SHADER_STAGE_COMPUTE_BIT,
574  },
575  { /* crc_ieee_buf */
576  .type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
577  .stages = VK_SHADER_STAGE_COMPUTE_BIT,
578  },
579  };
580  ff_vk_shader_add_descriptor_set(s, shd, desc_set_const, 2, 1, 0);
581 
582  const FFVulkanDescriptorSetBinding desc_set[] = {
583  { /* slice_data_buf */
584  .type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
585  .stages = VK_SHADER_STAGE_COMPUTE_BIT,
586  },
587  { /* slice_offsets_buf */
588  .type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
589  .stages = VK_SHADER_STAGE_COMPUTE_BIT,
590  },
591  { /* slice_status_buf */
592  .type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
593  .stages = VK_SHADER_STAGE_COMPUTE_BIT,
594  },
595  { /* fltmap_buf */
596  .type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
597  .stages = VK_SHADER_STAGE_COMPUTE_BIT,
598  },
599  };
600  ff_vk_shader_add_descriptor_set(s, shd, desc_set, 4, 0, 0);
601 
602  RET(ff_vk_shader_link(s, shd,
605 
606  RET(ff_vk_shader_register_exec(s, pool, shd));
607 
608 fail:
609  return err;
610 }
611 
613  FFVkExecPool *pool, FFVulkanShader *shd,
614  VkSpecializationInfo *sl, int ac)
615 {
616  int err;
617  int wg_dim = FFMIN(s->props.properties.limits.maxComputeWorkGroupSize[0], 1024);
618 
619  ff_vk_shader_load(shd, VK_SHADER_STAGE_COMPUTE_BIT, sl,
620  (uint32_t []) { wg_dim, 1, 1 }, 0);
621 
623  VK_SHADER_STAGE_COMPUTE_BIT);
624 
625  const FFVulkanDescriptorSetBinding desc_set_const[] = {
626  { /* rangecoder_buf */
627  .type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
628  .stages = VK_SHADER_STAGE_COMPUTE_BIT,
629  },
630  };
631  ff_vk_shader_add_descriptor_set(s, shd, desc_set_const, 1, 1, 0);
632 
633  const FFVulkanDescriptorSetBinding desc_set[] = {
634  { /* slice_data_buf */
635  .type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
636  .stages = VK_SHADER_STAGE_COMPUTE_BIT,
637  },
638  { /* slice_state_buf */
639  .type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
640  .stages = VK_SHADER_STAGE_COMPUTE_BIT,
641  },
642  };
643  ff_vk_shader_add_descriptor_set(s, shd, desc_set, 2, 0, 0);
644 
645  if (ac == AC_GOLOMB_RICE)
646  RET(ff_vk_shader_link(s, shd,
649  else
650  RET(ff_vk_shader_link(s, shd,
653 
654  RET(ff_vk_shader_register_exec(s, pool, shd));
655 
656 fail:
657  return err;
658 }
659 
661  FFVkExecPool *pool, FFVulkanShader *shd,
662  AVHWFramesContext *dec_frames_ctx,
663  AVHWFramesContext *out_frames_ctx,
664  VkSpecializationInfo *sl, int ac, int rgb,
665  int bayer)
666 {
667  int err;
668 
669  uint32_t wg_x = ac != AC_GOLOMB_RICE ? CONTEXT_SIZE : 1;
670  ff_vk_shader_load(shd, VK_SHADER_STAGE_COMPUTE_BIT, sl,
671  (uint32_t []) { wg_x, 1, 1 }, 0);
672 
674  VK_SHADER_STAGE_COMPUTE_BIT);
675 
676  const FFVulkanDescriptorSetBinding desc_set_const[] = {
677  { /* rangecoder_buf */
678  .type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
679  .stages = VK_SHADER_STAGE_COMPUTE_BIT,
680  },
681  { /* quant_buf */
682  .type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
683  .stages = VK_SHADER_STAGE_COMPUTE_BIT,
684  },
685  };
686  ff_vk_shader_add_descriptor_set(s, shd, desc_set_const, 2, 1, 0);
687 
688  const FFVulkanDescriptorSetBinding desc_set[] = {
689  { /* slice_data_buf */
690  .type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
691  .stages = VK_SHADER_STAGE_COMPUTE_BIT,
692  },
693  { /* slice_offsets_buf */
694  .type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
695  .stages = VK_SHADER_STAGE_COMPUTE_BIT,
696  },
697  { /* slice_status_buf */
698  .type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
699  .stages = VK_SHADER_STAGE_COMPUTE_BIT,
700  },
701  { /* slice_state_buf */
702  .type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
703  .stages = VK_SHADER_STAGE_COMPUTE_BIT,
704  },
705  { /* dec */
706  .type = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
707  .stages = VK_SHADER_STAGE_COMPUTE_BIT,
708  .elems = av_pix_fmt_count_planes(dec_frames_ctx->sw_format),
709  },
710  { /* dst */
711  .type = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
712  .stages = VK_SHADER_STAGE_COMPUTE_BIT,
713  .elems = av_pix_fmt_count_planes(out_frames_ctx->sw_format),
714  },
715  { /* fltmap_buf */
716  .type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
717  .stages = VK_SHADER_STAGE_COMPUTE_BIT,
718  },
719  };
720  /* Detect a float output from the pixfmt descriptor instead of f->flt:
721  * the encoder side does not (yet) write f->flt to the extradata, so the
722  * parsed value is unreliable for some v4m4+ streams. The descriptor's
723  * FLOAT flag is set by the pixfmt selection logic and is accurate */
724  int is_float = !!(av_pix_fmt_desc_get(out_frames_ctx->sw_format)->flags &
726 
727  /* Bindings 5 (dst) and 6 (fltmap_buf) are conditional */
728  ff_vk_shader_add_descriptor_set(s, shd, desc_set,
729  5 + rgb + (is_float && !bayer),
730  0, 0);
731 
732  if (bayer) {
733  if (ac == AC_GOLOMB_RICE)
734  ff_vk_shader_link(s, shd,
737  else
738  ff_vk_shader_link(s, shd,
741  } else if (is_float) {
742  if (ac == AC_GOLOMB_RICE)
743  ff_vk_shader_link(s, shd,
746  else
747  ff_vk_shader_link(s, shd,
750  } else if (ac == AC_GOLOMB_RICE) {
751  if (rgb)
752  ff_vk_shader_link(s, shd,
755  else
756  ff_vk_shader_link(s, shd,
759  } else {
760  if (rgb)
761  ff_vk_shader_link(s, shd,
764  else
765  ff_vk_shader_link(s, shd,
767  ff_ffv1_dec_comp_spv_len, "main");
768  }
769 
770  RET(ff_vk_shader_register_exec(s, pool, shd));
771 
772 fail:
773  return err;
774 }
775 
777  AVBufferRef **dst, enum AVPixelFormat sw_format)
778 {
779  int err;
780  AVHWFramesContext *frames_ctx;
781  AVVulkanFramesContext *vk_frames;
782  FFV1Context *f = avctx->priv_data;
783 
784  *dst = av_hwframe_ctx_alloc(s->device_ref);
785  if (!(*dst))
786  return AVERROR(ENOMEM);
787 
788  frames_ctx = (AVHWFramesContext *)((*dst)->data);
789  frames_ctx->format = AV_PIX_FMT_VULKAN;
790  frames_ctx->sw_format = sw_format;
791  frames_ctx->width = s->frames->width;
792  frames_ctx->height = f->num_v_slices*RGB_LINECACHE;
793 
794  vk_frames = frames_ctx->hwctx;
795  vk_frames->tiling = VK_IMAGE_TILING_OPTIMAL;
796  vk_frames->img_flags = VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT;
797  vk_frames->usage = VK_IMAGE_USAGE_STORAGE_BIT |
798  VK_IMAGE_USAGE_TRANSFER_DST_BIT;
799 
800  err = av_hwframe_ctx_init(*dst);
801  if (err < 0) {
802  av_log(avctx, AV_LOG_ERROR,
803  "Unable to initialize frame pool with format %s: %s\n",
804  av_get_pix_fmt_name(sw_format), av_err2str(err));
806  return err;
807  }
808 
809  return 0;
810 }
811 
813 {
814  FFv1VulkanDecodeContext *fv = ctx->sd_ctx;
815 
817 
818  ff_vk_shader_free(&ctx->s, &fv->setup);
819  ff_vk_shader_free(&ctx->s, &fv->reset);
820  ff_vk_shader_free(&ctx->s, &fv->decode);
821 
822  ff_vk_free_buf(&ctx->s, &fv->consts_buf);
823 
827 
828  av_freep(&fv);
829 }
830 
832 {
833  int err;
834  FFV1Context *f = avctx->priv_data;
838 
839  if (f->version < 3)
840  return AVERROR(ENOTSUP);
841 
842  /* Streams with a low amount of slices will usually be much slower
843  * to decode, so warn the user. */
844  if (f->slice_count < 16)
845  av_log(avctx, AV_LOG_WARNING, "Stream has a low number of slices (%i), "
846  "decoding may be very slow\n", f->slice_count);
847 
848  err = ff_vk_decode_init(avctx);
849  if (err < 0)
850  return err;
851  ctx = dec->shared_ctx;
852 
853  fv = ctx->sd_ctx = av_mallocz(sizeof(*fv));
854  if (!fv) {
855  err = AVERROR(ENOMEM);
856  goto fail;
857  }
858 
859  ctx->sd_ctx_free = &vk_decode_ffv1_uninit;
860 
862  AVHWFramesContext *dctx = hwfc;
863  enum AVPixelFormat sw_format = hwfc->sw_format;
864  int is_rgb = !(f->colorspace == 0 && sw_format != AV_PIX_FMT_YA8) &&
865  !(sw_format == AV_PIX_FMT_YA8);
866 
867  /* Intermediate frame pool for RCT */
868  if (is_rgb) {
869  RET(init_indirect(avctx, &ctx->s, &fv->intermediate_frames_ref,
870  f->use32bit ? AV_PIX_FMT_GBRAP32 : AV_PIX_FMT_GBRAP16));
872  }
873 
874  SPEC_LIST_CREATE(sl, 15, 15*sizeof(uint32_t))
875  ff_ffv1_vk_set_common_sl(avctx, f, sl, sw_format);
876 
877  if (RGB_LINECACHE != 2)
878  SPEC_LIST_ADD(sl, 0, 32, RGB_LINECACHE);
879 
880  if (f->ec && !!(avctx->err_recognition & AV_EF_CRCCHECK))
881  SPEC_LIST_ADD(sl, 1, 32, 1);
882 
883  /* Setup shader */
884  RET(init_setup_shader(f, &ctx->s, &ctx->exec_pool, &fv->setup, sl));
885 
886  /* Reset shader */
887  RET(init_reset_shader(f, &ctx->s, &ctx->exec_pool, &fv->reset, sl, f->ac));
888 
889  /* Decode shaders */
890  RET(init_decode_shader(f, &ctx->s, &ctx->exec_pool, &fv->decode,
891  dctx, hwfc, sl, f->ac, is_rgb, f->bayer));
892 
893  /* Init static data */
895 
896  /* Update setup global descriptors */
897  RET(ff_vk_shader_update_desc_buffer(&ctx->s, &ctx->exec_pool.contexts[0],
898  &fv->setup, 0, 0, 0,
899  &fv->consts_buf,
900  256*sizeof(uint32_t), 512*sizeof(uint8_t),
901  VK_FORMAT_UNDEFINED));
902  RET(ff_vk_shader_update_desc_buffer(&ctx->s, &ctx->exec_pool.contexts[0],
903  &fv->setup, 0, 1, 0,
904  &fv->consts_buf,
905  0, 256*sizeof(uint32_t),
906  VK_FORMAT_UNDEFINED));
907 
908  /* Update decode global descriptors */
909  RET(ff_vk_shader_update_desc_buffer(&ctx->s, &ctx->exec_pool.contexts[0],
910  &fv->decode, 0, 0, 0,
911  &fv->consts_buf,
912  256*sizeof(uint32_t), 512*sizeof(uint8_t),
913  VK_FORMAT_UNDEFINED));
914  RET(ff_vk_shader_update_desc_buffer(&ctx->s, &ctx->exec_pool.contexts[0],
915  &fv->decode, 0, 1, 0,
916  &fv->consts_buf,
917  256*sizeof(uint32_t) + 512*sizeof(uint8_t),
918  VK_WHOLE_SIZE,
919  VK_FORMAT_UNDEFINED));
920 
921 fail:
922  return err;
923 }
924 
926 {
927  AVHWDeviceContext *dev_ctx = _hwctx.nc;
928  AVVulkanDeviceContext *hwctx = dev_ctx->hwctx;
929 
931  FFVulkanDecodePicture *vp = &fp->vp;
932  FFVkBuffer *slice_feedback = (FFVkBuffer *)fp->slice_feedback_buf->data;
933  uint8_t *ssp = slice_feedback->mapped_mem + 2*fp->slice_num*sizeof(uint32_t);
934 
935  ff_vk_decode_free_frame(dev_ctx, vp);
936 
937  /* Invalidate slice/output data if needed */
938  if (!(slice_feedback->flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)) {
939  VkMappedMemoryRange invalidate_data = {
940  .sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,
941  .memory = slice_feedback->mem,
942  .offset = 0,
943  .size = 2*fp->slice_num*sizeof(uint32_t),
944  };
946  1, &invalidate_data);
947  }
948 
949  int slice_error_cnt = 0;
950  int crc_mismatch_cnt = 0;
951  uint32_t max_overread = 0;
952  for (int i = 0; i < fp->slice_num; i++) {
953  uint32_t crc_res = 0;
954  if (fp->crc_checked)
955  crc_res = AV_RN32(ssp + 2*i*sizeof(uint32_t) + 0);
956  uint32_t overread = AV_RN32(ssp + 2*i*sizeof(uint32_t) + 4);
957  max_overread = FFMAX(overread, max_overread);
958  slice_error_cnt += !!overread;
959  crc_mismatch_cnt += !!crc_res;
960  }
961  if (slice_error_cnt || crc_mismatch_cnt)
962  av_log(dev_ctx, AV_LOG_ERROR, "Decode status: %i slices overread (%i bytes max), "
963  "%i CRCs mismatched\n",
964  slice_error_cnt, max_overread, crc_mismatch_cnt);
965 
968 }
969 
971  .p.name = "ffv1_vulkan",
972  .p.type = AVMEDIA_TYPE_VIDEO,
973  .p.id = AV_CODEC_ID_FFV1,
974  .p.pix_fmt = AV_PIX_FMT_VULKAN,
975  .start_frame = &vk_ffv1_start_frame,
976  .decode_slice = &vk_ffv1_decode_slice,
977  .end_frame = &vk_ffv1_end_frame,
978  .free_frame_priv = &vk_ffv1_free_frame_priv,
979  .frame_priv_data_size = sizeof(FFv1VulkanDecodePicture),
983  .frame_params = &ff_vk_frame_params,
984  .priv_data_size = sizeof(FFVulkanDecodeContext),
986 };
flags
const SwsFlags flags[]
Definition: swscale.c:85
AVHWDeviceContext::hwctx
void * hwctx
The format-specific data, allocated and freed by libavutil along with this context.
Definition: hwcontext.h:88
ff_ffv1_dec_reset_comp_spv_len
const unsigned int ff_ffv1_dec_reset_comp_spv_len
AV_PIX_FMT_GBRAP16
#define AV_PIX_FMT_GBRAP16
Definition: pixfmt.h:565
AV_LOG_WARNING
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:216
AVPixelFormat
AVPixelFormat
Pixel format.
Definition: pixfmt.h:71
ff_ffv1_dec_reset_golomb_comp_spv_data
const unsigned char ff_ffv1_dec_reset_golomb_comp_spv_data[]
FFv1VulkanDecodeContext::slice_feedback_pool
AVBufferPool * slice_feedback_pool
Definition: vulkan_ffv1.c:94
ff_ffv1_dec_rgb_golomb_comp_spv_data
const unsigned char ff_ffv1_dec_rgb_golomb_comp_spv_data[]
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
AV_PIX_FMT_YA8
@ AV_PIX_FMT_YA8
8 bits gray, 8 bits alpha
Definition: pixfmt.h:140
ff_vk_shader_free
void ff_vk_shader_free(FFVulkanContext *s, FFVulkanShader *shd)
Free a shader.
Definition: vulkan.c:2853
AVBufferPool
The buffer pool.
Definition: buffer_internal.h:88
ff_vk_decode_prepare_frame_sdr
int ff_vk_decode_prepare_frame_sdr(FFVulkanDecodeContext *dec, AVFrame *pic, FFVulkanDecodePicture *vkpic, int is_current, enum FFVkShaderRepFormat rep_fmt, int alloc_dpb)
Software-defined decoder version of ff_vk_decode_prepare_frame.
Definition: vulkan_decode.c:258
av_pix_fmt_desc_get
const AVPixFmtDescriptor * av_pix_fmt_desc_get(enum AVPixelFormat pix_fmt)
Definition: pixdesc.c:3456
AVBufferRef::data
uint8_t * data
The data buffer.
Definition: buffer.h:90
FFVulkanDecodeContext::shared_ctx
FFVulkanDecodeShared * shared_ctx
Definition: vulkan_decode.h:55
RET
#define RET(x)
Definition: vulkan.h:68
AVRefStructOpaque
RefStruct is an API for creating reference-counted objects with minimal overhead.
Definition: refstruct.h:58
FFv1ShaderParams::fmt_lut
int fmt_lut[4]
Definition: ffv1_vulkan.h:39
AVHWFramesContext::format
enum AVPixelFormat format
The pixel format identifying the underlying HW surface type.
Definition: hwcontext.h:200
AVCodecContext::err_recognition
int err_recognition
Error recognition; may misdetect some more or less valid parts as errors.
Definition: avcodec.h:1416
AV_PIX_FMT_FLAG_FLOAT
#define AV_PIX_FMT_FLAG_FLOAT
The pixel format contains IEEE-754 floating point values.
Definition: pixdesc.h:158
AVRefStructOpaque::nc
void * nc
Definition: refstruct.h:59
FFVulkanDecodePicture::invalidate_memory_ranges
PFN_vkInvalidateMappedMemoryRanges invalidate_memory_ranges
Definition: vulkan_decode.h:105
FFHWAccel::p
AVHWAccel p
The public AVHWAccel.
Definition: hwaccel_internal.h:38
av_frame_free
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
Definition: frame.c:64
av_hwframe_ctx_init
int av_hwframe_ctx_init(AVBufferRef *ref)
Finalize the context before use.
Definition: hwcontext.c:337
AVFrame
This structure describes decoded (raw) audio or video data.
Definition: frame.h:466
av_hwframe_ctx_alloc
AVBufferRef * av_hwframe_ctx_alloc(AVBufferRef *device_ref_in)
Allocate an AVHWFramesContext tied to a given device context.
Definition: hwcontext.c:263
FFv1VulkanDecodePicture::slice_data_size
uint32_t slice_data_size
Definition: vulkan_ffv1.c:74
data
const char data[16]
Definition: mxf.c:149
FFVulkanDecodeDescriptor::codec_id
enum AVCodecID codec_id
Definition: vulkan_decode.h:30
FFVkBuffer::address
VkDeviceAddress address
Definition: vulkan.h:130
FFv1VulkanDecodePicture::slice_feedback_buf
AVBufferRef * slice_feedback_buf
Definition: vulkan_ffv1.c:77
ff_vk_exec_get
FFVkExecContext * ff_vk_exec_get(FFVulkanContext *s, FFVkExecPool *pool)
Retrieve an execution pool.
Definition: vulkan.c:568
FF_VK_REP_NATIVE
@ FF_VK_REP_NATIVE
Definition: vulkan.h:449
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
SPEC_LIST_ADD
#define SPEC_LIST_ADD(name, idx, val_bits, val)
Definition: vulkan.h:86
ff_ffv1_dec_rgb_float_golomb_comp_spv_data
const unsigned char ff_ffv1_dec_rgb_float_golomb_comp_spv_data[]
AVHWFramesContext::width
int width
The allocated dimensions of the frames in this pool.
Definition: hwcontext.h:220
ff_vk_exec_bind_shader
void ff_vk_exec_bind_shader(FFVulkanContext *s, FFVkExecContext *e, const FFVulkanShader *shd)
Bind a shader.
Definition: vulkan.c:2830
FFVulkanDecodeContext
Definition: vulkan_decode.h:54
AV_PIX_FMT_VULKAN
@ AV_PIX_FMT_VULKAN
Vulkan hardware images.
Definition: pixfmt.h:379
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:800
ff_ffv1_dec_bayer_golomb_comp_spv_data
const unsigned char ff_ffv1_dec_bayer_golomb_comp_spv_data[]
AVFrame::data
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition: frame.h:487
FFv1VulkanDecodeContext::slice_state_pool
AVBufferPool * slice_state_pool
Definition: vulkan_ffv1.c:92
av_pix_fmt_count_planes
int av_pix_fmt_count_planes(enum AVPixelFormat pix_fmt)
Definition: pixdesc.c:3496
rgb
Definition: rpzaenc.c:60
AV_PIX_FMT_GBRP14
#define AV_PIX_FMT_GBRP14
Definition: pixfmt.h:560
FFHWAccel
Definition: hwaccel_internal.h:34
AVVkFrame::img
VkImage img[AV_NUM_DATA_POINTERS]
Vulkan images to which the memory is bound to.
Definition: hwcontext_vulkan.h:318
ff_ffv1_dec_rgb_float_golomb_comp_spv_len
const unsigned int ff_ffv1_dec_rgb_float_golomb_comp_spv_len
FFv1VulkanDecodeContext::reset
FFVulkanShader reset
Definition: vulkan_ffv1.c:87
FFVulkanDecodePicture::sem_value
uint64_t sem_value
Definition: vulkan_decode.h:85
AV_PIX_FMT_GBRP10
#define AV_PIX_FMT_GBRP10
Definition: pixfmt.h:558
init_indirect
static int init_indirect(AVCodecContext *avctx, FFVulkanContext *s, AVBufferRef **dst, enum AVPixelFormat sw_format)
Definition: vulkan_ffv1.c:776
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:2781
AVVulkanFramesContext
Allocated as AVHWFramesContext.hwctx, used to set pool-specific options.
Definition: hwcontext_vulkan.h:223
ff_vk_frame_barrier
void ff_vk_frame_barrier(FFVulkanContext *s, FFVkExecContext *e, AVFrame *pic, VkImageMemoryBarrier2 *bar, int *nb_bar, VkPipelineStageFlags2 src_stage, VkPipelineStageFlags2 dst_stage, VkAccessFlagBits2 new_access, VkImageLayout new_layout, uint32_t new_qf)
Definition: vulkan.c:2093
HWACCEL_CAP_THREAD_SAFE
#define HWACCEL_CAP_THREAD_SAFE
Definition: hwaccel_internal.h:32
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:2646
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:1411
CONTEXT_SIZE
#define CONTEXT_SIZE
Definition: ffv1.h:45
FFv1VulkanDecodeContext::consts_buf
FFVkBuffer consts_buf
Definition: vulkan_ffv1.c:90
FFVulkanDecodeShared
Definition: vulkan_decode.h:38
ff_ffv1_dec_setup_comp_spv_data
const unsigned char ff_ffv1_dec_setup_comp_spv_data[]
av_unused
#define av_unused
Definition: attributes.h:164
AVHWDeviceContext
This struct aggregates all the (hardware/vendor-specific) "high-level" state, i.e.
Definition: hwcontext.h:63
av_frame_alloc
AVFrame * av_frame_alloc(void)
Allocate an AVFrame and set its fields to default values.
Definition: frame.c:52
FFVulkanDescriptorSetBinding::type
VkDescriptorType type
Definition: vulkan.h:114
ff_ffv1_dec_bayer_comp_spv_data
const unsigned char ff_ffv1_dec_bayer_comp_spv_data[]
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:210
AVHWFramesContext::height
int height
Definition: hwcontext.h:220
AV_FRAME_FLAG_KEY
#define AV_FRAME_FLAG_KEY
A flag to mark frames that are keyframes.
Definition: frame.h:681
init_reset_shader
static int init_reset_shader(FFV1Context *f, FFVulkanContext *s, FFVkExecPool *pool, FFVulkanShader *shd, VkSpecializationInfo *sl, int ac)
Definition: vulkan_ffv1.c:612
s
#define s(width, name)
Definition: cbs_vp9.c:198
FFVulkanDecodePicture
Definition: vulkan_decode.h:73
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:899
ff_ffv1_dec_setup_comp_spv_len
const unsigned int ff_ffv1_dec_setup_comp_spv_len
FFv1VulkanDecodeContext
Definition: vulkan_ffv1.c:83
FFv1VulkanDecodePicture::slice_fltmap_buf
AVBufferRef * slice_fltmap_buf
Definition: vulkan_ffv1.c:76
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:1592
AVVulkanFramesContext::img_flags
VkImageCreateFlags img_flags
Flags to set during image creation.
Definition: hwcontext_vulkan.h:276
AV_PIX_FMT_GBRAP32
#define AV_PIX_FMT_GBRAP32
Definition: pixfmt.h:566
ctx
static AVFormatContext * ctx
Definition: movenc.c:49
FFv1VulkanDecodePicture::vp
FFVulkanDecodePicture vp
Definition: vulkan_ffv1.c:69
vk_ffv1_decode_slice
static int vk_ffv1_decode_slice(AVCodecContext *avctx, const uint8_t *data, uint32_t size)
Definition: vulkan_ffv1.c:206
FFv1VulkanDecodePicture
Definition: vulkan_ffv1.c:68
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:640
av_mallocz
#define av_mallocz(s)
Definition: tableprint_vlc.h:31
vk_decode_ffv1_uninit
static void vk_decode_ffv1_uninit(FFVulkanDecodeShared *ctx)
Definition: vulkan_ffv1.c:812
FFv1VulkanDecodePicture::slice_state
AVBufferRef * slice_state
Definition: vulkan_ffv1.c:71
FFv1VulkanDecodePicture::plane_state_size
uint32_t plane_state_size
Definition: vulkan_ffv1.c:72
if
if(ret)
Definition: filter_design.txt:179
FFv1ShaderParams::extend_lookup
uint32_t extend_lookup[8]
Definition: ffv1_vulkan.h:36
ff_ffv1_dec_golomb_comp_spv_len
const unsigned int ff_ffv1_dec_golomb_comp_spv_len
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:717
fail
#define fail
Definition: test.h:478
AVVulkanDeviceContext
Main Vulkan context, allocated as AVHWDeviceContext.hwctx.
Definition: hwcontext_vulkan.h:59
ff_ffv1_vk_init_consts
int ff_ffv1_vk_init_consts(FFVulkanContext *s, FFVkBuffer *vkb, FFV1Context *f)
Definition: ffv1_vulkan.c:85
HWACCEL_CAP_ASYNC_SAFE
#define HWACCEL_CAP_ASYNC_SAFE
Header providing the internals of AVHWAccel.
Definition: hwaccel_internal.h:31
NULL
#define NULL
Definition: coverity.c:32
AVHWFramesContext::sw_format
enum AVPixelFormat sw_format
The pixel format identifying the actual data layout of the hardware frames.
Definition: hwcontext.h:213
AC_GOLOMB_RICE
#define AC_GOLOMB_RICE
Definition: ffv1.h:52
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
AVPixFmtDescriptor::nb_components
uint8_t nb_components
The number of components each pixel has, (1-4)
Definition: pixdesc.h:71
hwaccel_internal.h
ff_vk_decode_free_frame
void ff_vk_decode_free_frame(AVHWDeviceContext *dev_ctx, FFVulkanDecodePicture *vp)
Free a frame and its state.
Definition: vulkan_decode.c:694
AVCodecContext::internal
struct AVCodecInternal * internal
Private context used for internal data.
Definition: avcodec.h:478
vk_ffv1_end_frame
static int vk_ffv1_end_frame(AVCodecContext *avctx)
Definition: vulkan_ffv1.c:241
AV_RN32
#define AV_RN32(p)
Definition: intreadwrite.h:360
av_buffer_pool_uninit
void av_buffer_pool_uninit(AVBufferPool **ppool)
Mark the pool as being available for freeing.
Definition: buffer.c:328
ff_vk_decode_uninit
int ff_vk_decode_uninit(AVCodecContext *avctx)
Free decoder.
Definition: vulkan_decode.c:1300
ff_vk_shader_link
int ff_vk_shader_link(FFVulkanContext *s, FFVulkanShader *shd, const char *spirv, size_t spirv_len, const char *entrypoint)
Link a shader into an executable.
Definition: vulkan.c:2419
AVVulkanFramesContext::usage
VkImageUsageFlagBits usage
Defines extra usage of output frames.
Definition: hwcontext_vulkan.h:243
SPEC_LIST_CREATE
#define SPEC_LIST_CREATE(name, max_length, max_size)
Definition: vulkan.h:76
ffv1_vulkan.h
FFVkBuffer::mapped_mem
uint8_t * mapped_mem
Definition: vulkan.h:134
FFVulkanContext
Definition: vulkan.h:312
ff_ffv1_dec_rgb_float_comp_spv_len
const unsigned int ff_ffv1_dec_rgb_float_comp_spv_len
ff_vk_frame_params
int ff_vk_frame_params(AVCodecContext *avctx, AVBufferRef *hw_frames_ctx)
Initialize hw_frames_ctx with the parameters needed to decode the stream using the parameters from av...
Definition: vulkan_decode.c:1159
AV_EF_CRCCHECK
#define AV_EF_CRCCHECK
Verify checksums embedded in the bitstream (could be of either encoded or decoded data,...
Definition: defs.h:48
AVPixFmtDescriptor::flags
uint64_t flags
Combination of AV_PIX_FMT_FLAG_...
Definition: pixdesc.h:94
ff_ffv1_dec_rgb_float_comp_spv_data
const unsigned char ff_ffv1_dec_rgb_float_comp_spv_data[]
ff_ffv1_dec_golomb_comp_spv_data
const unsigned char ff_ffv1_dec_golomb_comp_spv_data[]
AV_CODEC_ID_FFV1
@ AV_CODEC_ID_FFV1
Definition: codec_id.h:85
f
f
Definition: af_crystalizer.c:122
ff_vk_buf_barrier
#define ff_vk_buf_barrier(dst, vkb, s_stage, s_access, s_access2, d_stage, d_access, d_access2, offs, bsz)
Definition: vulkan.h:551
init
int(* init)(AVBSFContext *ctx)
Definition: dts2pts.c:579
AVVkFrame::access
VkAccessFlagBits access[AV_NUM_DATA_POINTERS]
Updated after every barrier.
Definition: hwcontext_vulkan.h:342
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:2820
FFVulkanDescriptorSetBinding
Definition: vulkan.h:112
AV_WN32
#define AV_WN32(p, v)
Definition: intreadwrite.h:372
AVCodecInternal::hwaccel_priv_data
void * hwaccel_priv_data
hwaccel-specific private data
Definition: internal.h:130
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:313
i
#define i(width, name, range_min, range_max)
Definition: cbs_h264.c:63
av_err2str
#define av_err2str(errnum)
Convenience macro, the return value should be used only directly in function arguments but never stan...
Definition: error.h:122
for
for(k=2;k<=8;++k)
Definition: h264pred_template.c:424
vk_ffv1_free_frame_priv
static void vk_ffv1_free_frame_priv(AVRefStructOpaque _hwctx, void *data)
Definition: vulkan_ffv1.c:925
size
int size
Definition: twinvq_data.h:10344
AV_NUM_DATA_POINTERS
#define AV_NUM_DATA_POINTERS
Definition: frame.h:467
FFVulkanShader
Definition: vulkan.h:225
FFVkBuffer::flags
VkMemoryPropertyFlagBits flags
Definition: vulkan.h:128
FFv1VulkanDecodeContext::intermediate_frames_ref
AVBufferRef * intermediate_frames_ref
Definition: vulkan_ffv1.c:84
ff_ffv1_dec_rgb_comp_spv_len
const unsigned int ff_ffv1_dec_rgb_comp_spv_len
FFVkExecContext
Definition: vulkan.h:145
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:2794
ff_ffv1_dec_comp_spv_data
const unsigned char ff_ffv1_dec_comp_spv_data[]
ff_ffv1_vk_set_common_sl
void ff_ffv1_vk_set_common_sl(AVCodecContext *avctx, FFV1Context *f, VkSpecializationInfo *sl, enum AVPixelFormat sw_format)
Definition: ffv1_vulkan.c:24
AVHWAccel::name
const char * name
Name of the hardware accelerated codec.
Definition: avcodec.h:1967
FF_VK_EXT_EXTERNAL_HOST_MEMORY
#define FF_VK_EXT_EXTERNAL_HOST_MEMORY
Definition: vulkan_functions.h:36
uninit
static void uninit(AVBSFContext *ctx)
Definition: pcm_rechunk.c:68
ff_ffv1_dec_comp_spv_len
const unsigned int ff_ffv1_dec_comp_spv_len
FFVulkanDecodePicture::out
VkImageView out[AV_NUM_DATA_POINTERS]
Definition: vulkan_decode.h:78
ff_vk_exec_start
int ff_vk_exec_start(FFVulkanContext *s, FFVkExecContext *e)
Start/submit/wait an execution.
Definition: vulkan.c:580
FFv1VulkanDecodePicture::slice_state_size
uint32_t slice_state_size
Definition: vulkan_ffv1.c:73
AV_PIX_FMT_GBRP12
#define AV_PIX_FMT_GBRP12
Definition: pixfmt.h:559
FFMIN
#define FFMIN(a, b)
Definition: macros.h:49
ffv1.h
FFVkBuffer::mem
VkDeviceMemory mem
Definition: vulkan.h:127
FFVulkanDecodePicture::sem
VkSemaphore sem
Definition: vulkan_decode.h:84
init_decode_shader
static int init_decode_shader(FFV1Context *f, FFVulkanContext *s, FFVkExecPool *pool, FFVulkanShader *shd, AVHWFramesContext *dec_frames_ctx, AVHWFramesContext *out_frames_ctx, VkSpecializationInfo *sl, int ac, int rgb, int bayer)
Definition: vulkan_ffv1.c:660
FFv1VulkanDecodeContext::slice_fltmap_pool
AVBufferPool * slice_fltmap_pool
Definition: vulkan_ffv1.c:93
ff_vk_free_buf
void ff_vk_free_buf(FFVulkanContext *s, FFVkBuffer *buf)
Definition: vulkan.c:1264
ff_ffv1_dec_reset_golomb_comp_spv_len
const unsigned int ff_ffv1_dec_reset_golomb_comp_spv_len
AVCodecContext::hw_frames_ctx
AVBufferRef * hw_frames_ctx
A reference to the AVHWFramesContext describing the input (for encoding) or output (decoding) frames.
Definition: avcodec.h:1471
AVHWFramesContext
This struct describes a set or pool of "hardware" frames (i.e.
Definition: hwcontext.h:118
ff_ffv1_vulkan_hwaccel
const FFHWAccel ff_ffv1_vulkan_hwaccel
Definition: vulkan_ffv1.c:970
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:2010
AVHWFramesContext::hwctx
void * hwctx
The format-specific data, allocated and freed automatically along with this context.
Definition: hwcontext.h:153
FFVkExecPool
Definition: vulkan.h:290
ff_vk_decode_add_slice
int ff_vk_decode_add_slice(AVCodecContext *avctx, FFVulkanDecodePicture *vp, const uint8_t *data, size_t size, int add_startcode, uint32_t *nb_slices, const uint32_t **offsets)
Add slice data to frame.
Definition: vulkan_decode.c:305
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:1509
FFVulkanDecodePicture::view
struct FFVulkanDecodePicture::@343 view
init_setup_shader
static int init_setup_shader(FFV1Context *f, FFVulkanContext *s, FFVkExecPool *pool, FFVulkanShader *shd, VkSpecializationInfo *sl)
Definition: vulkan_ffv1.c:558
AVCodecContext
main external API structure.
Definition: avcodec.h:443
ff_vk_shader_add_descriptor_set
int ff_vk_shader_add_descriptor_set(FFVulkanContext *s, FFVulkanShader *shd, const FFVulkanDescriptorSetBinding *desc, int nb, int singular, int print_to_shader_only)
Add descriptor to a shader.
Definition: vulkan.c:2546
FFv1VulkanDecodeContext::decode
FFVulkanShader decode
Definition: vulkan_ffv1.c:88
ff_vk_dec_ffv1_desc
const FFVulkanDecodeDescriptor ff_vk_dec_ffv1_desc
Definition: vulkan_ffv1.c:63
buffer
the frame and frame reference mechanism is intended to as much as expensive copies of that data while still allowing the filters to produce correct results The data is stored in buffers represented by AVFrame structures Several references can point to the same frame buffer
Definition: filter_design.txt:49
ff_ffv1_dec_bayer_golomb_comp_spv_len
const unsigned int ff_ffv1_dec_bayer_golomb_comp_spv_len
update_thread_context
the pkt_dts and pkt_pts fields in AVFrame will work as usual Restrictions on codec whose streams don t reset across will not work because their bitstreams cannot be decoded in parallel *The contents of buffers must not be read before as well as code calling up to before the decode process starts Call have update_thread_context() run it in the next thread. Add AV_CODEC_CAP_FRAME_THREADS to the codec capabilities. There will be very little speed gain at this point but it should work. Use ff_thread_get_buffer()(or ff_progress_frame_get_buffer() in case you have inter-frame dependencies and use the ProgressFrame API) to allocate frame buffers. Call ff_progress_frame_report() after some part of the current picture has decoded. A good place to put this is where draw_horiz_band() is called - add this if it isn 't called anywhere
FFVulkanDecodeDescriptor
Definition: vulkan_decode.h:29
FFv1VulkanDecodePicture::slice_offset
uint32_t * slice_offset
Definition: vulkan_ffv1.c:78
ff_ffv1_dec_reset_comp_spv_data
const unsigned char ff_ffv1_dec_reset_comp_spv_data[]
FFVulkanDecodePicture::dpb_frame
AVFrame * dpb_frame
Definition: vulkan_decode.h:74
ff_vk_update_thread_context
int ff_vk_update_thread_context(AVCodecContext *dst, const AVCodecContext *src)
Synchronize the contexts between 2 threads.
Definition: vulkan_decode.c:142
AVVulkanFramesContext::tiling
VkImageTiling tiling
Controls the tiling of allocated frames.
Definition: hwcontext_vulkan.h:232
AVMEDIA_TYPE_VIDEO
@ AVMEDIA_TYPE_VIDEO
Definition: avutil.h:200
FFVulkanDecodePicture::slices_buf
AVBufferRef * slices_buf
Definition: vulkan_decode.h:99
mem.h
AVVkFrame::layout
VkImageLayout layout[AV_NUM_DATA_POINTERS]
Definition: hwcontext_vulkan.h:343
AVBufferRef
A reference to a data buffer.
Definition: buffer.h:82
AVVulkanDeviceContext::act_dev
VkDevice act_dev
Active device.
Definition: hwcontext_vulkan.h:84
vulkan_decode.h
FFV1Context
Definition: ffv1.h:122
FFv1ShaderParams
Definition: ffv1_vulkan.h:33
ff_vk_count_images
static int ff_vk_count_images(AVVkFrame *f)
Definition: vulkan.h:366
FFALIGN
#define FFALIGN(x, a)
Definition: macros.h:78
AVCodecContext::priv_data
void * priv_data
Definition: avcodec.h:470
FFv1VulkanDecodeContext::setup
FFVulkanShader setup
Definition: vulkan_ffv1.c:86
ff_ffv1_dec_bayer_comp_spv_len
const unsigned int ff_ffv1_dec_bayer_comp_spv_len
av_freep
#define av_freep(p)
Definition: tableprint_vlc.h:35
FFVkBuffer
Definition: vulkan.h:125
FFv1ShaderParams::context_count
uint16_t context_count[8]
Definition: ffv1_vulkan.h:37
ff_vk_exec_submit
int ff_vk_exec_submit(FFVulkanContext *s, FFVkExecContext *e)
Definition: vulkan.c:925
ff_ffv1_dec_rgb_golomb_comp_spv_len
const unsigned int ff_ffv1_dec_rgb_golomb_comp_spv_len
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:27
ff_vk_decode_init
int ff_vk_decode_init(AVCodecContext *avctx)
Initialize decoder.
Definition: vulkan_decode.c:1311
AVCodecContext::sw_pix_fmt
enum AVPixelFormat sw_pix_fmt
Nominal unaccelerated pixel format, see AV_PIX_FMT_xxx.
Definition: avcodec.h:650
FFv1ShaderParams::slice_data
VkDeviceAddress slice_data
Definition: ffv1_vulkan.h:34
FFv1VulkanDecodePicture::crc_checked
int crc_checked
Definition: vulkan_ffv1.c:80
ff_ffv1_dec_rgb_comp_spv_data
const unsigned char ff_ffv1_dec_rgb_comp_spv_data[]
RGB_LINECACHE
#define RGB_LINECACHE
Definition: vulkan_ffv1.c:28
av_hwframe_get_buffer
int av_hwframe_get_buffer(AVBufferRef *hwframe_ref, AVFrame *frame, int flags)
Allocate a new frame attached to the given AVHWFramesContext.
Definition: hwcontext.c:506
FFVulkanFunctions
Definition: vulkan_functions.h:275
ff_vk_shader_load
int ff_vk_shader_load(FFVulkanShader *shd, VkPipelineStageFlags stage, VkSpecializationInfo *spec, uint32_t wg_size[3], uint32_t required_subgroup_size)
Initialize a shader object.
Definition: vulkan.c:2136
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:1306
vk_ffv1_start_frame
static int vk_ffv1_start_frame(AVCodecContext *avctx, const AVBufferRef *buffer_ref, av_unused const uint8_t *buffer, av_unused uint32_t size)
Definition: vulkan_ffv1.c:97
vk_decode_ffv1_init
static int vk_decode_ffv1_init(AVCodecContext *avctx)
Definition: vulkan_ffv1.c:831
av_get_pix_fmt_name
const char * av_get_pix_fmt_name(enum AVPixelFormat pix_fmt)
Return the short name for a pixel format, NULL in case pix_fmt is unknown.
Definition: pixdesc.c:3376
FFv1VulkanDecodePicture::slice_num
int slice_num
Definition: vulkan_ffv1.c:79