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  /* The context-less free callback needs these device functions, which
186  * prepare_frame_sdr() used to set. vp->sem is kept for the next
187  * non-keyframe's wait and the free callback's CRC readback. */
188  vp->wait_semaphores = ctx->s.vkfn.WaitSemaphores;
189  vp->invalidate_memory_ranges = ctx->s.vkfn.InvalidateMappedMemoryRanges;
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 output_views[AV_NUM_DATA_POINTERS];
269  VkImageView rct_image_views[AV_NUM_DATA_POINTERS];
270 
271  VkImageMemoryBarrier2 img_bar[37];
272  int nb_img_bar = 0;
273  VkBufferMemoryBarrier2 buf_bar[8];
274  int nb_buf_bar = 0;
275 
276  FFVkExecContext *exec = ff_vk_exec_get(&ctx->s, &ctx->exec_pool);
277  ff_vk_exec_start(&ctx->s, exec);
278 
279  /* Prepare deps */
280  RET(ff_vk_exec_add_dep_frame(&ctx->s, exec, f->picture.f,
281  VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
282  VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT));
283 
284  err = ff_vk_exec_mirror_sem_value(&ctx->s, exec, &vp->sem, &vp->sem_value,
285  f->picture.f);
286  if (err < 0)
287  return err;
288 
289  /* Exec-owned output views (vp->sem is still mirrored above, for the next
290  * frame's dependency and the free callback's CRC readback). */
291  RET(ff_vk_create_imageviews(&ctx->s, exec, output_views, f->picture.f,
293 
294  if (is_rgb) {
295  RET(ff_vk_create_imageviews(&ctx->s, exec, rct_image_views,
297  RET(ff_vk_exec_add_dep_frame(&ctx->s, exec, vp->dpb_frame,
298  VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
299  VK_PIPELINE_STAGE_2_CLEAR_BIT));
300  }
301 
302  if (!(f->picture.f->flags & AV_FRAME_FLAG_KEY)) {
303  FFv1VulkanDecodePicture *fpl = f->hwaccel_last_picture_private;
304  FFVulkanDecodePicture *vpl = &fpl->vp;
305 
306  /* Wait on the previous frame */
307  RET(ff_vk_exec_add_dep_wait_sem(&ctx->s, exec, vpl->sem, vpl->sem_value,
308  VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT));
309  }
310 
311  RET(ff_vk_exec_add_dep_buf(&ctx->s, exec, &fp->slice_state, 1, 1));
312  RET(ff_vk_exec_add_dep_buf(&ctx->s, exec, &fp->slice_feedback_buf, 1, 1));
313  RET(ff_vk_exec_add_dep_buf(&ctx->s, exec, &vp->slices_buf, 1, 0));
314  vp->slices_buf = NULL;
315 
316  if (fp->slice_fltmap_buf) {
317  RET(ff_vk_exec_add_dep_buf(&ctx->s, exec, &fp->slice_fltmap_buf, 1, 0));
318  fp->slice_fltmap_buf = NULL;
319  }
320 
321  AVVkFrame *vkf = (AVVkFrame *)f->picture.f->data[0];
322  for (int i = 0; i < ff_vk_count_images(vkf); i++) {
323  vkf->layout[i] = VK_IMAGE_LAYOUT_UNDEFINED;
324  vkf->access[i] = VK_ACCESS_2_NONE;
325  }
326 
327  /* Setup shader */
328  ff_vk_shader_update_desc_buffer(&ctx->s, exec, &fv->setup,
329  1, 0, 0,
330  slice_state,
331  0, fp->slice_data_size*f->slice_count,
332  VK_FORMAT_UNDEFINED);
333  ff_vk_shader_update_desc_buffer(&ctx->s, exec, &fv->setup,
334  1, 1, 0,
335  slice_feedback,
336  0, 2*f->slice_count*sizeof(uint32_t),
337  VK_FORMAT_UNDEFINED);
338  ff_vk_shader_update_desc_buffer(&ctx->s, exec, &fv->setup,
339  1, 2, 0,
340  slice_feedback,
341  2*f->slice_count*sizeof(uint32_t),
342  VK_WHOLE_SIZE,
343  VK_FORMAT_UNDEFINED);
344  if (fltmap_buf)
345  ff_vk_shader_update_desc_buffer(&ctx->s, exec, &fv->setup,
346  1, 3, 0,
347  fltmap_buf,
348  0,
349  VK_WHOLE_SIZE,
350  VK_FORMAT_UNDEFINED);
351 
352  ff_vk_exec_bind_shader(&ctx->s, exec, &fv->setup);
353 
354  FFv1ShaderParams pd = {
355  .slice_data = slices_buf->address,
356 
357  .img_size[0] = f->picture.f->width,
358  .img_size[1] = f->picture.f->height,
359 
360  .plane_state_size = fp->plane_state_size,
361  .key_frame = f->picture.f->flags & AV_FRAME_FLAG_KEY,
362  .crcref = f->crcref,
363  .micro_version = f->micro_version,
364  };
365 
366  for (int i = 0; i < f->quant_table_count; i++) {
367  pd.context_count[i] = f->context_count[i];
368  pd.extend_lookup[i] = f->quant_tables[i][3][127] ||
369  f->quant_tables[i][4][127];
370  }
371 
372  /* For some reason the C FFv1 encoder/decoder treats these differently */
373  if (sw_format == AV_PIX_FMT_GBRP10 || sw_format == AV_PIX_FMT_GBRP12 ||
374  sw_format == AV_PIX_FMT_GBRP14)
375  memcpy(pd.fmt_lut, (int [4]) { 2, 1, 0, 3 }, 4*sizeof(int));
376  else
377  ff_vk_set_perm(sw_format, pd.fmt_lut, 0);
378 
379  ff_vk_shader_update_push_const(&ctx->s, exec, &fv->setup,
380  VK_SHADER_STAGE_COMPUTE_BIT,
381  0, sizeof(FFv1ShaderParams), &pd);
382 
383  vk->CmdDispatch(exec->buf, f->num_h_slices, f->num_v_slices, 1);
384 
385  if (is_rgb) {
386  vkf = (AVVkFrame *)vp->dpb_frame->data[0];
387  for (int i = 0; i < 4; i++) {
388  vkf->layout[i] = VK_IMAGE_LAYOUT_UNDEFINED;
389  vkf->access[i] = VK_ACCESS_2_NONE;
390  }
391 
392  ff_vk_frame_barrier(&ctx->s, exec, vp->dpb_frame, img_bar, &nb_img_bar,
393  VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
394  VK_PIPELINE_STAGE_2_CLEAR_BIT,
395  VK_ACCESS_2_TRANSFER_WRITE_BIT,
396  VK_IMAGE_LAYOUT_GENERAL,
397  VK_QUEUE_FAMILY_IGNORED);
398 
399  vk->CmdPipelineBarrier2(exec->buf, &(VkDependencyInfo) {
400  .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
401  .pImageMemoryBarriers = img_bar,
402  .imageMemoryBarrierCount = nb_img_bar,
403  .pBufferMemoryBarriers = buf_bar,
404  .bufferMemoryBarrierCount = nb_buf_bar,
405  });
406  nb_img_bar = 0;
407  nb_buf_bar = 0;
408 
409  /* The intermediate frame has 4 planes (GBRAP16/32). Clear all of
410  * them since the bayer decoder uses all four. */
411  int n_dec_planes = f->bayer ? 4 : color_planes;
412  for (int i = 0; i < n_dec_planes; i++)
413  vk->CmdClearColorImage(exec->buf, vkf->img[i], VK_IMAGE_LAYOUT_GENERAL,
414  &((VkClearColorValue) { 0 }),
415  1, &((VkImageSubresourceRange) {
416  .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
417  .levelCount = 1,
418  .layerCount = 1,
419  }));
420  }
421 
422  /* Sync between setup and reset shaders */
423  ff_vk_buf_barrier(buf_bar[nb_buf_bar++], slice_state,
424  COMPUTE_SHADER_BIT, SHADER_STORAGE_READ_BIT,
425  SHADER_STORAGE_WRITE_BIT,
426  COMPUTE_SHADER_BIT, SHADER_STORAGE_READ_BIT, NONE_KHR,
427  0, fp->slice_data_size*f->slice_count);
428 
429  /* Probability data barrier for P-frames */
430  if (!(f->picture.f->flags & AV_FRAME_FLAG_KEY))
431  ff_vk_buf_barrier(buf_bar[nb_buf_bar++], slice_state,
432  COMPUTE_SHADER_BIT, SHADER_STORAGE_READ_BIT,
433  SHADER_STORAGE_WRITE_BIT,
434  COMPUTE_SHADER_BIT, SHADER_STORAGE_WRITE_BIT, NONE_KHR,
435  fp->slice_data_size*f->slice_count, VK_WHOLE_SIZE);
436 
437  vk->CmdPipelineBarrier2(exec->buf, &(VkDependencyInfo) {
438  .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
439  .pImageMemoryBarriers = img_bar,
440  .imageMemoryBarrierCount = nb_img_bar,
441  .pBufferMemoryBarriers = buf_bar,
442  .bufferMemoryBarrierCount = nb_buf_bar,
443  });
444  nb_buf_bar = 0;
445  nb_img_bar = 0;
446 
447  /* Reset shader */
448  ff_vk_shader_update_desc_buffer(&ctx->s, exec, &fv->reset,
449  1, 0, 0,
450  slice_state,
451  0, fp->slice_data_size*f->slice_count,
452  VK_FORMAT_UNDEFINED);
453  ff_vk_shader_update_desc_buffer(&ctx->s, exec, &fv->reset,
454  1, 1, 0,
455  slice_state,
456  f->slice_count*fp->slice_data_size,
457  VK_WHOLE_SIZE,
458  VK_FORMAT_UNDEFINED);
459 
460  ff_vk_exec_bind_shader(&ctx->s, exec, &fv->reset);
461  ff_vk_shader_update_push_const(&ctx->s, exec, &fv->reset,
462  VK_SHADER_STAGE_COMPUTE_BIT,
463  0, sizeof(FFv1ShaderParams), &pd);
464 
465  vk->CmdDispatch(exec->buf, f->num_h_slices, f->num_v_slices,
466  f->plane_count);
467 
468  /* Sync probabilities between reset and decode shaders */
469  ff_vk_buf_barrier(buf_bar[nb_buf_bar++], slice_state,
470  COMPUTE_SHADER_BIT, SHADER_STORAGE_WRITE_BIT, NONE_KHR,
471  COMPUTE_SHADER_BIT, SHADER_STORAGE_READ_BIT,
472  SHADER_STORAGE_WRITE_BIT,
473  fp->slice_data_size*f->slice_count, VK_WHOLE_SIZE);
474 
475  /* Input frame barrier */
476  ff_vk_frame_barrier(&ctx->s, exec, f->picture.f, img_bar, &nb_img_bar,
477  VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
478  VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT,
479  VK_ACCESS_SHADER_WRITE_BIT |
480  (!is_rgb ? VK_ACCESS_SHADER_READ_BIT : 0),
481  VK_IMAGE_LAYOUT_GENERAL,
482  VK_QUEUE_FAMILY_IGNORED);
483  if (is_rgb)
484  ff_vk_frame_barrier(&ctx->s, exec, vp->dpb_frame, img_bar, &nb_img_bar,
485  VK_PIPELINE_STAGE_2_CLEAR_BIT,
486  VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT,
487  VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT,
488  VK_IMAGE_LAYOUT_GENERAL,
489  VK_QUEUE_FAMILY_IGNORED);
490 
491  vk->CmdPipelineBarrier2(exec->buf, &(VkDependencyInfo) {
492  .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
493  .pImageMemoryBarriers = img_bar,
494  .imageMemoryBarrierCount = nb_img_bar,
495  .pBufferMemoryBarriers = buf_bar,
496  .bufferMemoryBarrierCount = nb_buf_bar,
497  });
498  nb_img_bar = 0;
499  nb_buf_bar = 0;
500 
501  /* Decode */
503  1, 0, 0,
504  slice_state,
505  0, fp->slice_data_size*f->slice_count,
506  VK_FORMAT_UNDEFINED);
508  1, 1, 0,
509  slice_feedback,
510  0, 2*f->slice_count*sizeof(uint32_t),
511  VK_FORMAT_UNDEFINED);
513  1, 2, 0,
514  slice_feedback,
515  2*f->slice_count*sizeof(uint32_t),
516  VK_WHOLE_SIZE,
517  VK_FORMAT_UNDEFINED);
519  1, 3, 0,
520  slice_state,
521  f->slice_count*fp->slice_data_size,
522  VK_WHOLE_SIZE,
523  VK_FORMAT_UNDEFINED);
524 
525  AVFrame *decode_dst = is_rgb ? vp->dpb_frame : f->picture.f;
526  VkImageView *decode_dst_view = is_rgb ? rct_image_views : output_views;
527  ff_vk_shader_update_img_array(&ctx->s, exec, &fv->decode,
528  decode_dst, decode_dst_view,
529  1, 4,
530  VK_IMAGE_LAYOUT_GENERAL,
531  VK_NULL_HANDLE);
532  if (is_rgb)
533  ff_vk_shader_update_img_array(&ctx->s, exec, &fv->decode,
534  f->picture.f, output_views,
535  1, 5,
536  VK_IMAGE_LAYOUT_GENERAL,
537  VK_NULL_HANDLE);
538  if (fltmap_buf)
540  1, 6, 0,
541  fltmap_buf,
542  0,
543  VK_WHOLE_SIZE,
544  VK_FORMAT_UNDEFINED);
545 
546  ff_vk_exec_bind_shader(&ctx->s, exec, &fv->decode);
547  ff_vk_shader_update_push_const(&ctx->s, exec, &fv->decode,
548  VK_SHADER_STAGE_COMPUTE_BIT,
549  0, sizeof(FFv1ShaderParams), &pd);
550 
551  vk->CmdDispatch(exec->buf, f->num_h_slices, f->num_v_slices, 1);
552 
553  err = ff_vk_exec_submit(&ctx->s, exec);
554  if (err < 0)
555  return err;
556 
557  /* We don't need the temporary frame after decoding */
558  av_frame_free(&vp->dpb_frame);
559 
560 fail:
561  return 0;
562 }
563 
565  FFVkExecPool *pool, FFVulkanShader *shd,
566  VkSpecializationInfo *sl)
567 {
568  int err;
569 
570  ff_vk_shader_load(shd, VK_SHADER_STAGE_COMPUTE_BIT, sl,
571  (uint32_t []) { 1, 1, 1 }, 0);
572 
574  VK_SHADER_STAGE_COMPUTE_BIT);
575 
576  const FFVulkanDescriptorSetBinding desc_set_const[] = {
577  { /* rangecoder_buf */
578  .type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
579  .stages = VK_SHADER_STAGE_COMPUTE_BIT,
580  },
581  { /* crc_ieee_buf */
582  .type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
583  .stages = VK_SHADER_STAGE_COMPUTE_BIT,
584  },
585  };
586  ff_vk_shader_add_descriptor_set(s, shd, desc_set_const, 2, 1, 0);
587 
588  const FFVulkanDescriptorSetBinding desc_set[] = {
589  { /* slice_data_buf */
590  .type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
591  .stages = VK_SHADER_STAGE_COMPUTE_BIT,
592  },
593  { /* slice_offsets_buf */
594  .type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
595  .stages = VK_SHADER_STAGE_COMPUTE_BIT,
596  },
597  { /* slice_status_buf */
598  .type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
599  .stages = VK_SHADER_STAGE_COMPUTE_BIT,
600  },
601  { /* fltmap_buf */
602  .type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
603  .stages = VK_SHADER_STAGE_COMPUTE_BIT,
604  },
605  };
606  ff_vk_shader_add_descriptor_set(s, shd, desc_set, 4, 0, 0);
607 
608  RET(ff_vk_shader_link(s, shd,
611 
612  RET(ff_vk_shader_register_exec(s, pool, shd));
613 
614 fail:
615  return err;
616 }
617 
619  FFVkExecPool *pool, FFVulkanShader *shd,
620  VkSpecializationInfo *sl, int ac)
621 {
622  int err;
623  int wg_dim = FFMIN(s->props.properties.limits.maxComputeWorkGroupSize[0], 1024);
624 
625  ff_vk_shader_load(shd, VK_SHADER_STAGE_COMPUTE_BIT, sl,
626  (uint32_t []) { wg_dim, 1, 1 }, 0);
627 
629  VK_SHADER_STAGE_COMPUTE_BIT);
630 
631  const FFVulkanDescriptorSetBinding desc_set_const[] = {
632  { /* rangecoder_buf */
633  .type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
634  .stages = VK_SHADER_STAGE_COMPUTE_BIT,
635  },
636  };
637  ff_vk_shader_add_descriptor_set(s, shd, desc_set_const, 1, 1, 0);
638 
639  const FFVulkanDescriptorSetBinding desc_set[] = {
640  { /* slice_data_buf */
641  .type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
642  .stages = VK_SHADER_STAGE_COMPUTE_BIT,
643  },
644  { /* slice_state_buf */
645  .type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
646  .stages = VK_SHADER_STAGE_COMPUTE_BIT,
647  },
648  };
649  ff_vk_shader_add_descriptor_set(s, shd, desc_set, 2, 0, 0);
650 
651  if (ac == AC_GOLOMB_RICE)
652  RET(ff_vk_shader_link(s, shd,
655  else
656  RET(ff_vk_shader_link(s, shd,
659 
660  RET(ff_vk_shader_register_exec(s, pool, shd));
661 
662 fail:
663  return err;
664 }
665 
667  FFVkExecPool *pool, FFVulkanShader *shd,
668  AVHWFramesContext *dec_frames_ctx,
669  AVHWFramesContext *out_frames_ctx,
670  VkSpecializationInfo *sl, int ac, int rgb,
671  int bayer)
672 {
673  int err;
674 
675  uint32_t wg_x = ac != AC_GOLOMB_RICE ? CONTEXT_SIZE : 1;
676  ff_vk_shader_load(shd, VK_SHADER_STAGE_COMPUTE_BIT, sl,
677  (uint32_t []) { wg_x, 1, 1 }, 0);
678 
680  VK_SHADER_STAGE_COMPUTE_BIT);
681 
682  const FFVulkanDescriptorSetBinding desc_set_const[] = {
683  { /* rangecoder_buf */
684  .type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
685  .stages = VK_SHADER_STAGE_COMPUTE_BIT,
686  },
687  { /* quant_buf */
688  .type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
689  .stages = VK_SHADER_STAGE_COMPUTE_BIT,
690  },
691  };
692  ff_vk_shader_add_descriptor_set(s, shd, desc_set_const, 2, 1, 0);
693 
694  const FFVulkanDescriptorSetBinding desc_set[] = {
695  { /* slice_data_buf */
696  .type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
697  .stages = VK_SHADER_STAGE_COMPUTE_BIT,
698  },
699  { /* slice_offsets_buf */
700  .type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
701  .stages = VK_SHADER_STAGE_COMPUTE_BIT,
702  },
703  { /* slice_status_buf */
704  .type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
705  .stages = VK_SHADER_STAGE_COMPUTE_BIT,
706  },
707  { /* slice_state_buf */
708  .type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
709  .stages = VK_SHADER_STAGE_COMPUTE_BIT,
710  },
711  { /* dec */
712  .type = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
713  .stages = VK_SHADER_STAGE_COMPUTE_BIT,
714  .elems = av_pix_fmt_count_planes(dec_frames_ctx->sw_format),
715  },
716  { /* dst */
717  .type = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
718  .stages = VK_SHADER_STAGE_COMPUTE_BIT,
719  .elems = av_pix_fmt_count_planes(out_frames_ctx->sw_format),
720  },
721  { /* fltmap_buf */
722  .type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
723  .stages = VK_SHADER_STAGE_COMPUTE_BIT,
724  },
725  };
726  /* Detect a float output from the pixfmt descriptor instead of f->flt:
727  * the encoder side does not (yet) write f->flt to the extradata, so the
728  * parsed value is unreliable for some v4m4+ streams. The descriptor's
729  * FLOAT flag is set by the pixfmt selection logic and is accurate */
730  int is_float = !!(av_pix_fmt_desc_get(out_frames_ctx->sw_format)->flags &
732 
733  /* Bindings 5 (dst) and 6 (fltmap_buf) are conditional */
734  ff_vk_shader_add_descriptor_set(s, shd, desc_set,
735  5 + rgb + (is_float && !bayer),
736  0, 0);
737 
738  if (bayer) {
739  if (ac == AC_GOLOMB_RICE)
740  ff_vk_shader_link(s, shd,
743  else
744  ff_vk_shader_link(s, shd,
747  } else if (is_float) {
748  if (ac == AC_GOLOMB_RICE)
749  ff_vk_shader_link(s, shd,
752  else
753  ff_vk_shader_link(s, shd,
756  } else if (ac == AC_GOLOMB_RICE) {
757  if (rgb)
758  ff_vk_shader_link(s, shd,
761  else
762  ff_vk_shader_link(s, shd,
765  } else {
766  if (rgb)
767  ff_vk_shader_link(s, shd,
770  else
771  ff_vk_shader_link(s, shd,
773  ff_ffv1_dec_comp_spv_len, "main");
774  }
775 
776  RET(ff_vk_shader_register_exec(s, pool, shd));
777 
778 fail:
779  return err;
780 }
781 
783  AVBufferRef **dst, enum AVPixelFormat sw_format)
784 {
785  int err;
786  AVHWFramesContext *frames_ctx;
787  AVVulkanFramesContext *vk_frames;
788  FFV1Context *f = avctx->priv_data;
789 
790  *dst = av_hwframe_ctx_alloc(s->device_ref);
791  if (!(*dst))
792  return AVERROR(ENOMEM);
793 
794  frames_ctx = (AVHWFramesContext *)((*dst)->data);
795  frames_ctx->format = AV_PIX_FMT_VULKAN;
796  frames_ctx->sw_format = sw_format;
797  frames_ctx->width = s->frames->width;
798  frames_ctx->height = f->num_v_slices*RGB_LINECACHE;
799 
800  vk_frames = frames_ctx->hwctx;
801  vk_frames->tiling = VK_IMAGE_TILING_OPTIMAL;
802  vk_frames->img_flags = VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT;
803  vk_frames->usage = VK_IMAGE_USAGE_STORAGE_BIT |
804  VK_IMAGE_USAGE_TRANSFER_DST_BIT;
805 
806  err = av_hwframe_ctx_init(*dst);
807  if (err < 0) {
808  av_log(avctx, AV_LOG_ERROR,
809  "Unable to initialize frame pool with format %s: %s\n",
810  av_get_pix_fmt_name(sw_format), av_err2str(err));
812  return err;
813  }
814 
815  return 0;
816 }
817 
819 {
820  FFv1VulkanDecodeContext *fv = ctx->sd_ctx;
821 
823 
824  ff_vk_shader_free(&ctx->s, &fv->setup);
825  ff_vk_shader_free(&ctx->s, &fv->reset);
826  ff_vk_shader_free(&ctx->s, &fv->decode);
827 
828  ff_vk_free_buf(&ctx->s, &fv->consts_buf);
829 
833 
834  av_freep(&fv);
835 }
836 
838 {
839  int err;
840  FFV1Context *f = avctx->priv_data;
844 
845  if (f->version < 3)
846  return AVERROR(ENOTSUP);
847 
848  /* Streams with a low amount of slices will usually be much slower
849  * to decode, so warn the user. */
850  if (f->slice_count < 16)
851  av_log(avctx, AV_LOG_WARNING, "Stream has a low number of slices (%i), "
852  "decoding may be very slow\n", f->slice_count);
853 
854  err = ff_vk_decode_init(avctx);
855  if (err < 0)
856  return err;
857  ctx = dec->shared_ctx;
858 
859  fv = ctx->sd_ctx = av_mallocz(sizeof(*fv));
860  if (!fv) {
861  err = AVERROR(ENOMEM);
862  goto fail;
863  }
864 
865  ctx->sd_ctx_free = &vk_decode_ffv1_uninit;
866 
868  AVHWFramesContext *dctx = hwfc;
869  enum AVPixelFormat sw_format = hwfc->sw_format;
870  int is_rgb = !(f->colorspace == 0 && sw_format != AV_PIX_FMT_YA8) &&
871  !(sw_format == AV_PIX_FMT_YA8);
872 
873  /* Intermediate frame pool for RCT */
874  if (is_rgb) {
875  RET(init_indirect(avctx, &ctx->s, &fv->intermediate_frames_ref,
876  f->use32bit ? AV_PIX_FMT_GBRAP32 : AV_PIX_FMT_GBRAP16));
878  }
879 
880  SPEC_LIST_CREATE(sl, 15, 15*sizeof(uint32_t))
881  ff_ffv1_vk_set_common_sl(avctx, f, sl, sw_format);
882 
883  if (RGB_LINECACHE != 2)
884  SPEC_LIST_ADD(sl, 0, 32, RGB_LINECACHE);
885 
886  if (f->ec && !!(avctx->err_recognition & AV_EF_CRCCHECK))
887  SPEC_LIST_ADD(sl, 1, 32, 1);
888 
889  /* Setup shader */
890  RET(init_setup_shader(f, &ctx->s, &ctx->exec_pool, &fv->setup, sl));
891 
892  /* Reset shader */
893  RET(init_reset_shader(f, &ctx->s, &ctx->exec_pool, &fv->reset, sl, f->ac));
894 
895  /* Decode shaders */
896  RET(init_decode_shader(f, &ctx->s, &ctx->exec_pool, &fv->decode,
897  dctx, hwfc, sl, f->ac, is_rgb, f->bayer));
898 
899  /* Init static data */
901 
902  /* Update setup global descriptors */
903  RET(ff_vk_shader_update_desc_buffer(&ctx->s, &ctx->exec_pool.contexts[0],
904  &fv->setup, 0, 0, 0,
905  &fv->consts_buf,
906  256*sizeof(uint32_t), 512*sizeof(uint8_t),
907  VK_FORMAT_UNDEFINED));
908  RET(ff_vk_shader_update_desc_buffer(&ctx->s, &ctx->exec_pool.contexts[0],
909  &fv->setup, 0, 1, 0,
910  &fv->consts_buf,
911  0, 256*sizeof(uint32_t),
912  VK_FORMAT_UNDEFINED));
913 
914  /* Update decode global descriptors */
915  RET(ff_vk_shader_update_desc_buffer(&ctx->s, &ctx->exec_pool.contexts[0],
916  &fv->decode, 0, 0, 0,
917  &fv->consts_buf,
918  256*sizeof(uint32_t), 512*sizeof(uint8_t),
919  VK_FORMAT_UNDEFINED));
920  RET(ff_vk_shader_update_desc_buffer(&ctx->s, &ctx->exec_pool.contexts[0],
921  &fv->decode, 0, 1, 0,
922  &fv->consts_buf,
923  256*sizeof(uint32_t) + 512*sizeof(uint8_t),
924  VK_WHOLE_SIZE,
925  VK_FORMAT_UNDEFINED));
926 
927 fail:
928  return err;
929 }
930 
932 {
933  AVHWDeviceContext *dev_ctx = _hwctx.nc;
934  AVVulkanDeviceContext *hwctx = dev_ctx->hwctx;
935 
937  FFVulkanDecodePicture *vp = &fp->vp;
938  FFVkBuffer *slice_feedback = (FFVkBuffer *)fp->slice_feedback_buf->data;
939  uint8_t *ssp = slice_feedback->mapped_mem + 2*fp->slice_num*sizeof(uint32_t);
940 
941  ff_vk_decode_free_frame(dev_ctx, vp);
942 
943  /* Invalidate slice/output data if needed */
944  if (!(slice_feedback->flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)) {
945  VkMappedMemoryRange invalidate_data = {
946  .sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,
947  .memory = slice_feedback->mem,
948  .offset = 0,
949  .size = 2*fp->slice_num*sizeof(uint32_t),
950  };
952  1, &invalidate_data);
953  }
954 
955  int slice_error_cnt = 0;
956  int crc_mismatch_cnt = 0;
957  uint32_t max_overread = 0;
958  for (int i = 0; i < fp->slice_num; i++) {
959  uint32_t crc_res = 0;
960  if (fp->crc_checked)
961  crc_res = AV_RN32(ssp + 2*i*sizeof(uint32_t) + 0);
962  uint32_t overread = AV_RN32(ssp + 2*i*sizeof(uint32_t) + 4);
963  max_overread = FFMAX(overread, max_overread);
964  slice_error_cnt += !!overread;
965  crc_mismatch_cnt += !!crc_res;
966  }
967  if (slice_error_cnt || crc_mismatch_cnt)
968  av_log(dev_ctx, AV_LOG_ERROR, "Decode status: %i slices overread (%i bytes max), "
969  "%i CRCs mismatched\n",
970  slice_error_cnt, max_overread, crc_mismatch_cnt);
971 
974 }
975 
977  .p.name = "ffv1_vulkan",
978  .p.type = AVMEDIA_TYPE_VIDEO,
979  .p.id = AV_CODEC_ID_FFV1,
980  .p.pix_fmt = AV_PIX_FMT_VULKAN,
981  .start_frame = &vk_ffv1_start_frame,
982  .decode_slice = &vk_ffv1_decode_slice,
983  .end_frame = &vk_ffv1_end_frame,
984  .free_frame_priv = &vk_ffv1_free_frame_priv,
985  .frame_priv_data_size = sizeof(FFv1VulkanDecodePicture),
989  .frame_params = &ff_vk_frame_params,
990  .priv_data_size = sizeof(FFVulkanDecodeContext),
992 };
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
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:472
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:493
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:266
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:782
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:171
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:687
flags
#define flags(name, subs,...)
Definition: cbs_av1.c:504
init_reset_shader
static int init_reset_shader(FFV1Context *f, FFVulkanContext *s, FFVkExecPool *pool, FFVulkanShader *shd, VkSpecializationInfo *sl, int ac)
Definition: vulkan_ffv1.c:618
FFVulkanDecodePicture::wait_semaphores
PFN_vkWaitSemaphores wait_semaphores
Definition: vulkan_decode.h:103
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:224
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:818
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:647
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:1253
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:191
SPEC_LIST_CREATE
#define SPEC_LIST_CREATE(name, max_length, max_size)
Definition: vulkan.h:76
ffv1_vulkan.h
AVVkFrame::access
VkAccessFlagBits2 access[AV_NUM_DATA_POINTERS]
Updated after every barrier.
Definition: hwcontext_vulkan.h:290
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:1112
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:83
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:608
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:261
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:931
size
int size
Definition: twinvq_data.h:10344
AV_NUM_DATA_POINTERS
#define AV_NUM_DATA_POINTERS
Definition: frame.h:473
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:1954
FF_VK_EXT_EXTERNAL_HOST_MEMORY
#define FF_VK_EXT_EXTERNAL_HOST_MEMORY
Definition: vulkan_functions.h:36
ff_ffv1_dec_comp_spv_len
const unsigned int ff_ffv1_dec_comp_spv_len
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
s
uint8_t s
Definition: llvidencdsp.c:39
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:666
uninit
static av_cold void uninit(AVBitStreamFilterContext *ctx)
Definition: lcevc_merge.c:135
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:976
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:258
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
init_setup_shader
static int init_setup_shader(FFV1Context *f, FFVulkanContext *s, FFVkExecPool *pool, FFVulkanShader *shd, VkSpecializationInfo *sl)
Definition: vulkan_ffv1.c:564
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:180
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:291
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:1264
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:837
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