FFmpeg
Loading...
Searching...
No Matches
apv_encode_vulkan.c
Go to the documentation of this file.
1/*
2 * Copyright (c) 2026 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 <math.h>
22#include <stdlib.h>
23
24#include "libavutil/mem.h"
25#include "libavutil/opt.h"
26#include "libavutil/pixdesc.h"
27#include "libavutil/vulkan.h"
28
29#include "avcodec.h"
30#include "codec_internal.h"
31#include "encode.h"
32#include "hwconfig.h"
33#include "vulkan_video.h"
34#include "internal.h"
35
36#include "apv.h"
37#include "cbs.h"
38#include "cbs_apv.h"
39
40extern const unsigned char ff_apv_encode_dct_comp_spv_data[];
41extern const unsigned int ff_apv_encode_dct_comp_spv_len;
42
43extern const unsigned char ff_apv_encode_tiles_comp_spv_data[];
44extern const unsigned int ff_apv_encode_tiles_comp_spv_len;
45
46#define APV_DEFAULT_QMAT 16
47#define APV_MAX_NUM_COMP 4
48
49typedef struct DCTPushData {
50 int frame_dim[2];
51 int tile_count[2];
56 float qf[APV_MAX_NUM_COMP]; /* per-component fact/(level_scale*2^qp_shift) */
57 uint8_t qmat[64]; /* quantisation matrix, raster order */
59
60typedef struct EntropyPushData {
61 VkDeviceAddress bytestream;
62 int tile_count[2];
64 uint32_t slot_size;
65 uint32_t comp_base; /* component index this dispatch's z=0 maps to */
66 uint32_t blocks_per_tile; /* uniform coeff stride, in blocks */
67 int frame_mb[2]; /* frame size in MBs (luma basis) */
68 int tile_mb_dim[2]; /* full-tile size in MBs */
69 uint32_t blocks_per_mb; /* blocks per MB of this dispatch's components */
71
84
85typedef struct VulkanEncodeAPVContext {
86 const AVClass *class;
87
91
93 FFVulkanShader shd_entropy[2]; /* [0] luma-sized, [1] chroma-sized */
95
96 /* Per-frame buffer pools */
101
102 /* DCT/quantize push constants -- encoder-constant, built once at init. */
104
105 /* CBS used to assemble the output packet */
109
111
112 /* Async machinery */
115
116 /* Derived per-encoder state */
117 int frame_mb_x, frame_mb_y; /* MBs in the frame (luma basis) */
119 int tile_mb_w, tile_mb_h; /* MBs per tile (luma basis) */
121 int blocks_per_mb; /* luma; always 4 */
122 int chroma_blocks_per_mb; /* 4 for 4:4:4, 2 for 4:2:2 */
126
131
132 size_t coeffs_size; /* total size of coeffs buffer */
133 size_t bytestream_size; /* total size of bytestream buffer */
134 size_t slot_size; /* per-tile-component bytestream slot size */
135 size_t sizes_size; /* total size of sizes buffer */
136
137 /* User options */
140 int qp_y;
141 int qp_c;
142 int qmatrix; /* APV_QMATRIX_*: quantisation matrix select */
143
144 /* Benchmark knob (env APV_VULKAN_HEADERS_ONLY): the GPU still encodes,
145 * but the tiles are never downloaded and packets carry headers only. */
147
148 /* Benchmark knob (env APV_VULKAN_SKIP_ENTROPY): skip the entropy
149 * dispatch to isolate the DCT pass. Implies headers_only. */
152
153/*
154 * HEVC default 8x8 intra scaling list (ITU-T H.265, Table 7-6): flat through
155 * the low-frequency core, a gentle ramp toward the high-frequency corner.
156 * Raster order; the matrix is symmetric, so APV's [y][x]/[x][y] indexing is
157 * immaterial. APV and HEVC share the "16 = neutral" convention, so the list
158 * transfers without rescaling.
159 */
160static const uint8_t apv_qmat_hevc_intra[64] = {
161 16, 16, 16, 16, 17, 18, 21, 24,
162 16, 16, 16, 16, 17, 19, 22, 25,
163 16, 16, 17, 18, 20, 22, 25, 29,
164 16, 16, 18, 21, 24, 27, 31, 36,
165 17, 17, 20, 24, 30, 35, 41, 47,
166 18, 19, 22, 27, 35, 44, 54, 65,
167 21, 22, 25, 31, 41, 54, 70, 88,
168 24, 25, 29, 36, 47, 65, 88, 115,
169};
170
171enum {
172 APV_QMATRIX_FLAT = 0, /* uniform 16 (the spec default) */
173 APV_QMATRIX_HEVC = 1, /* HEVC default intra scaling list */
174};
175
176/*
177 * The active quantisation-matrix value at raster index i. Both the q_matrix
178 * signalled in the frame header and the encoder's pf table are derived from
179 * this single accessor, so they cannot disagree -- a mismatch would quantise
180 * against a different matrix than the decoder dequantises with.
181 */
182static int apv_qmatrix_value(int qmatrix, int i)
183{
184 return qmatrix == APV_QMATRIX_HEVC ? apv_qmat_hevc_intra[i]
186}
187
188static const uint8_t apv_level_scale[6] = { 40, 45, 51, 57, 64, 71 };
189
191{
192 switch (sw_fmt) {
205 default:
206 return -1;
207 }
208}
209
211{
212 switch (sw_fmt) {
220 default: return -1;
221 }
222}
223
225{
226 int err;
228 FFVulkanShader *shd = &ev->shd_dct;
229
230 SPEC_LIST_CREATE(sl, 1, sizeof(uint32_t))
231 SPEC_LIST_ADD(sl, 16, 32, 4); /* nb_blocks: blocks_per_mb per workgroup */
232
233 ff_vk_shader_load(shd, VK_SHADER_STAGE_COMPUTE_BIT, sl,
234 (uint32_t []) { 8, 4, 1 }, 0);
235
237 VK_SHADER_STAGE_COMPUTE_BIT);
238
239 const FFVulkanDescriptorSetBinding desc_set[] = {
240 {
241 .name = "coeffs_buf",
242 .type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
243 .stages = VK_SHADER_STAGE_COMPUTE_BIT,
244 },
245 {
246 .name = "src",
247 .type = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
248 .stages = VK_SHADER_STAGE_COMPUTE_BIT,
250 },
251 };
252 ff_vk_shader_add_descriptor_set(&ev->s, shd, desc_set, 2, 0);
253
254 RET(ff_vk_shader_link(&ev->s, shd,
257
258 RET(ff_vk_shader_register_exec(&ev->s, &ev->exec_pool, shd));
259
260fail:
261 return err;
262}
263
264static int init_entropy_shader(AVCodecContext *avctx, int blocks_per_mb,
265 FFVulkanShader *shd)
266{
267 int err;
269
270 /* One workgroup per tile-component, one invocation per transform block.
271 * Luma and chroma tile-components hold different block counts under
272 * chroma sub-sampling, so each gets a pipeline with its own size. */
273 uint32_t wg = ev->tile_mb_w * ev->tile_mb_h * blocks_per_mb;
274 uint32_t min_sg = ev->s.subgroup_props.minSubgroupSize;
275
276 /* The driver picks the subgroup size; size for the most it may use */
277 SPEC_LIST_CREATE(sl, 1, sizeof(uint32_t))
278 SPEC_LIST_ADD(sl, 0, 32, FFALIGN(wg, min_sg) / min_sg);
279
280 ff_vk_shader_load(shd, VK_SHADER_STAGE_COMPUTE_BIT, sl,
281 (uint32_t []) { wg, 1, 1 }, 0);
282
284 VK_SHADER_STAGE_COMPUTE_BIT);
285
286 const FFVulkanDescriptorSetBinding desc_set[] = {
287 {
288 .name = "coeffs_buf",
289 .type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
290 .stages = VK_SHADER_STAGE_COMPUTE_BIT,
291 },
292 {
293 .name = "sizes_buf",
294 .type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
295 .stages = VK_SHADER_STAGE_COMPUTE_BIT,
296 },
297 };
298 ff_vk_shader_add_descriptor_set(&ev->s, shd, desc_set, 2, 0);
299
300 RET(ff_vk_shader_link(&ev->s, shd,
303
304 RET(ff_vk_shader_register_exec(&ev->s, &ev->exec_pool, shd));
305
306fail:
307 return err;
308}
309
310/*
311 * The DCT/quantize shader's push constants are entirely encoder-constant:
312 * frame geometry, the per-component quant scale qf, and the quantisation
313 * matrix. Build them once -- nothing here changes between frames.
314 */
316{
319 DCTPushData *pd = &ev->dct_push;
320 const double fact = (double)(1 << (ev->bit_depth - 1));
321
322 pd->frame_dim[0] = avctx->width;
323 pd->frame_dim[1] = avctx->height;
324 pd->tile_count[0] = ev->tile_cols;
325 pd->tile_count[1] = ev->tile_rows;
326 pd->tile_mb_dim[0] = ev->tile_mb_w;
327 pd->tile_mb_dim[1] = ev->tile_mb_h;
328 pd->log2_chroma_sub[0] = desc->log2_chroma_w;
329 pd->log2_chroma_sub[1] = desc->log2_chroma_h;
330 pd->num_comp = ev->num_comp;
331 pd->bit_depth = ev->bit_depth;
332
333 /*
334 * qf[c] = fact / (level_scale * 2^qp_shift). The encoder uses one QP per
335 * component, so this never varies by tile. Component 3 is alpha
336 * (4:4:4:4): full-resolution, so it takes the luma QP.
337 */
338 for (int c = 0; c < APV_MAX_NUM_COMP; c++) {
339 int qp = (c == 0 || c == 3) ? ev->qp_y : ev->qp_c;
340 int level_scale = apv_level_scale[qp % 6];
341 int qp_shift = qp / 6;
342 pd->qf[c] =
343 (float)(fact / ((double)level_scale * (double)(1 << qp_shift)));
344 }
345
346 /*
347 * The 8-bit quantisation matrix. The shader stages it to shared memory
348 * and quantises with 1024 / qmat[i], the reciprocal partner of the
349 * decoder's per-coefficient dequant -- the same matrix that gets
350 * signalled in the frame header.
351 */
352 for (int i = 0; i < 64; i++)
353 pd->qmat[i] = apv_qmatrix_value(ev->qmatrix, i);
354}
355
357 AVFrame *frame)
358{
359 int err = 0;
361 FFVulkanFunctions *vk = &ev->s.vkfn;
363 VkImageView views[AV_NUM_DATA_POINTERS];
364
365 VkImageMemoryBarrier2 img_bar[AV_NUM_DATA_POINTERS];
366 int nb_img_bar = 0;
367 VkBufferMemoryBarrier2 buf_bar[4];
368 int nb_buf_bar = 0;
369
370 FFVkBuffer *coeffs_buf;
371 FFVkBuffer *bytestream_buf;
372
373 FFVkBuffer *compacted_buf;
374 FFVkBuffer *sizes_buf;
375
376 fd->color_primaries = frame->color_primaries;
377 fd->color_trc = frame->color_trc;
378 fd->colorspace = frame->colorspace;
379 fd->color_range = frame->color_range;
380
381 /* Start recording */
382 err = ff_vk_exec_start(&ev->s, exec);
383 if (err < 0)
384 return err;
385
386 /* Allocate per-frame buffers */
388 VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,
389 NULL, ev->coeffs_size,
390 VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT));
391 coeffs_buf = fd->coeffs_ref;
392
393 /* The entropy shader writes the bitstream here, sparsely -- one
394 * worst-case-sized slot per tile-component. Device-local, so those GPU
395 * writes stay in VRAM and never cross PCIe. */
397 &fd->bytestream_ref,
398 VK_BUFFER_USAGE_STORAGE_BUFFER_BIT |
399 VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT,
401 VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT));
402 bytestream_buf = fd->bytestream_ref;
403
404 /* The compaction shader gathers the sparse slots into here, and the CPU
405 * assembles the packet from it. */
407 &fd->compacted_ref,
408 VK_BUFFER_USAGE_STORAGE_BUFFER_BIT |
409 VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT,
411 VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
412 VK_MEMORY_PROPERTY_HOST_CACHED_BIT));
413 compacted_buf = fd->compacted_ref;
414
416 VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,
417 NULL, ev->sizes_size,
418 VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
419 VK_MEMORY_PROPERTY_HOST_CACHED_BIT));
420 sizes_buf = fd->sizes_ref;
421
426
428 VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
429 VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT));
430
431 RET(ff_vk_create_imageviews(&ev->s, exec, views, frame, FF_VK_REP_INT));
432
433 ff_vk_frame_barrier(&ev->s, exec, frame,
434 img_bar, &nb_img_bar,
435 VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
436 VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT,
437 VK_ACCESS_SHADER_READ_BIT,
438 VK_IMAGE_LAYOUT_GENERAL,
439 VK_QUEUE_FAMILY_IGNORED);
440
441 vk->CmdPipelineBarrier2(exec->buf, &(VkDependencyInfo) {
442 .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
443 .pImageMemoryBarriers = img_bar,
444 .imageMemoryBarrierCount = nb_img_bar,
445 });
446 nb_img_bar = 0;
447
448 /* DCT + Quantize pass */
449 {
451 0, 0, 0,
452 coeffs_buf, 0, coeffs_buf->size,
453 VK_FORMAT_UNDEFINED);
454 ff_vk_shader_update_img_array(&ev->s, exec, &ev->shd_dct,
455 frame, views,
456 0, 1,
457 VK_IMAGE_LAYOUT_GENERAL,
458 VK_NULL_HANDLE);
459
460 ff_vk_exec_bind_shader(&ev->s, exec, &ev->shd_dct);
462 VK_SHADER_STAGE_COMPUTE_BIT,
463 0, sizeof(ev->dct_push), &ev->dct_push);
464
465 vk->CmdDispatch(exec->buf,
466 ev->frame_mb_x, ev->frame_mb_y, ev->num_comp);
467 }
468
469 /* Barrier: wait for coeff writes before entropy */
470 ff_vk_buf_barrier(buf_bar[nb_buf_bar++], coeffs_buf,
471 COMPUTE_SHADER_BIT, SHADER_WRITE_BIT, NONE,
472 COMPUTE_SHADER_BIT, SHADER_READ_BIT, NONE,
473 0, coeffs_buf->size);
474
475 vk->CmdPipelineBarrier2(exec->buf, &(VkDependencyInfo) {
476 .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
477 .pBufferMemoryBarriers = buf_bar,
478 .bufferMemoryBarrierCount = nb_buf_bar,
479 });
480 nb_buf_bar = 0;
481
482 /*
483 * Entropy encoding pass. Luma (component 0) and chroma (components
484 * 1..num_comp-1) run as two dispatches: under chroma sub-sampling their
485 * tile-components hold different block counts, hence different workgroup
486 * sizes -- one pipeline each. The two write disjoint memory and need no
487 * barrier between them, so the GPU is free to overlap them.
488 */
489 for (int p = 0; !ev->skip_entropy && p < 2; p++) {
490 FFVulkanShader *shd = &ev->shd_entropy[p];
491 uint32_t z_comps = (p == 0) ? 1 : ev->num_comp - 1;
492
493 if (z_comps == 0)
494 continue; /* 4:0:0 (monochrome) has no chroma components */
495
496 EntropyPushData pd = {
497 .bytestream = bytestream_buf->address,
498 .tile_count = { ev->tile_cols, ev->tile_rows },
499 .num_comp = ev->num_comp,
500 .slot_size = (uint32_t)ev->slot_size,
501 .comp_base = (uint32_t)p,
502 .blocks_per_tile = (uint32_t)ev->tile_mb_w * ev->tile_mb_h *
503 ev->blocks_per_mb,
504 .frame_mb = { ev->frame_mb_x, ev->frame_mb_y },
505 .tile_mb_dim = { ev->tile_mb_w, ev->tile_mb_h },
506 .blocks_per_mb = (uint32_t)(p == 0 ? ev->blocks_per_mb
508 };
509
510 ff_vk_shader_update_desc_buffer(&ev->s, exec, shd, 0, 0, 0,
511 coeffs_buf, 0, coeffs_buf->size,
512 VK_FORMAT_UNDEFINED);
513 ff_vk_shader_update_desc_buffer(&ev->s, exec, shd, 0, 1, 0,
514 sizes_buf, 0, sizes_buf->size,
515 VK_FORMAT_UNDEFINED);
516
517 ff_vk_exec_bind_shader(&ev->s, exec, shd);
518 ff_vk_shader_update_push_const(&ev->s, exec, shd,
519 VK_SHADER_STAGE_COMPUTE_BIT,
520 0, sizeof(pd), &pd);
521
522 vk->CmdDispatch(exec->buf, ev->tile_cols, ev->tile_rows, z_comps);
523 }
524
525 /* Compaction pass: gather the sparse per-tile-component slots into the
526 * output buffer. */
527 if (!ev->headers_only)
528 RET(ff_vk_seg_gather(&ev->s, exec, &ev->shd_compact,
529 sizes_buf, 0, ev->tile_count * ev->num_comp,
530 bytestream_buf, ev->slot_size,
531 compacted_buf, 0, 0));
532
533 err = ff_vk_exec_submit(&ev->s, exec);
534 if (err < 0)
535 return err;
536
537 return 0;
538
539fail:
540 ff_vk_exec_discard(&ev->s, exec);
541 return err;
542}
543
545 AVPacket *pkt)
546{
547 int err = 0;
549 FFVulkanFunctions *vk = &ev->s.vkfn;
551 FFVkBuffer *compacted_buf = fd->compacted_ref;
552 FFVkBuffer *sizes_buf = fd->sizes_ref;
553 APVRawFrame *raw_frame = &ev->raw_frame;
554
555 /* Wait for the GPU encode to finish */
556 ff_vk_exec_wait(&ev->s, exec);
557
558 const uint32_t *sizes = NULL;
559 static uint8_t headers_only_tile; /* 1-byte token tile data */
560
561 /* Headers-only benchmark mode never touches the GPU output. */
562 if (!ev->headers_only) {
563 /* Invalidate mapped memory if needed */
564 if (!(compacted_buf->flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)) {
565 VkMappedMemoryRange r = {
566 .sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,
567 .memory = compacted_buf->mem,
568 .offset = 0,
569 .size = VK_WHOLE_SIZE,
570 };
571 vk->InvalidateMappedMemoryRanges(ev->s.hwctx->act_dev, 1, &r);
572 }
573 if (!(sizes_buf->flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)) {
574 VkMappedMemoryRange r = {
575 .sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,
576 .memory = sizes_buf->mem,
577 .offset = 0,
578 .size = VK_WHOLE_SIZE,
579 };
580 vk->InvalidateMappedMemoryRanges(ev->s.hwctx->act_dev, 1, &r);
581 }
582 sizes = (const uint32_t *)sizes_buf->mapped_mem;
583 }
584
585 memset(raw_frame, 0, sizeof(*raw_frame));
586
588 raw_frame->pbu_header.group_id = 1;
589
590 APVRawFrameHeader *fh = &raw_frame->frame_header;
593 fh->frame_info.band_idc = ev->band_idc;
594 fh->frame_info.frame_width = avctx->width;
595 fh->frame_info.frame_height = avctx->height;
599
607 fh->full_range_flag;
608
609 /* compute_pf_table() builds the encoder's pf scale from the same matrix;
610 * the two must stay in sync. use_q_matrix is only signalled when the
611 * matrix is non-uniform (a flat 16 matrix is the inferred default). */
613 for (int c = 0; c < ev->num_comp; c++)
614 for (int y = 0; y < 8; y++)
615 for (int x = 0; x < 8; x++)
616 fh->quantization_matrix.q_matrix[c][y][x] =
617 apv_qmatrix_value(ev->qmatrix, y * 8 + x);
618
622
623 /* Populate each tile. The compacted buffer holds each tile-component's
624 * data back to back, in (tile, component) order -- the same layout the
625 * gather shader produced. */
626 uint32_t comp_off = 0;
627 for (int t = 0; t < ev->tile_count; t++) {
628 APVRawTile *tile = &raw_frame->tile[t];
629 uint32_t total_tile_data = 0;
630
631 tile->tile_header.tile_header_size =
632 4 + ev->num_comp * (4 + 1) + 1;
633 tile->tile_header.tile_index = t;
634
635 for (int c = 0; c < ev->num_comp; c++) {
636 uint32_t sz;
637 if (ev->headers_only) {
638 /* No readback: one token byte (CBS requires size >= 1). */
639 sz = 1;
640 tile->tile_data[c] = &headers_only_tile;
641 } else {
642 sz = sizes[t * ev->num_comp + c];
643 tile->tile_data[c] = compacted_buf->mapped_mem + comp_off;
644 comp_off += sz;
645 }
646 tile->tile_header.tile_data_size[c] = sz;
647 tile->tile_header.tile_qp[c] =
648 (c == 0 || c == 3) ? ev->qp_y : ev->qp_c;
649 total_tile_data += sz;
650 }
651 tile->tile_header.reserved_zero_8bits = 0;
652 tile->tile_dummy_byte_size = 0;
653 tile->tile_dummy_byte = NULL;
654
655 raw_frame->tile_size[t] =
656 tile->tile_header.tile_header_size + total_tile_data;
657 }
658
659 /* Assemble fragment using cbs_apv */
660 ff_cbs_fragment_reset(&ev->au);
661
662 err = ff_cbs_insert_unit_content(&ev->au, -1, APV_PBU_PRIMARY_FRAME,
663 raw_frame, NULL);
664 if (err < 0)
665 return err;
666
667 /* Assemble straight into the packet: ff_cbs_write_packet() hands pkt a
668 * reference to CBS's own assembled buffer -- no copy. */
669 err = ff_cbs_write_packet(ev->cbc, pkt, &ev->au);
670 if (err < 0)
671 return err;
672
673 av_log(avctx, AV_LOG_VERBOSE, "Encoded APV frame: %i bytes (%.2f MiB)\n",
674 pkt->size, pkt->size / (1024.0 * 1024.0));
675
680
681 return 0;
682}
683
685 AVPacket *pkt)
686{
688 return ff_vk_encode_loop_receive_packet(avctx, &ev->loop, pkt);
689}
690
692{
694 ff_vk_encode_loop_flush(avctx, &ev->loop);
695}
696
698{
700
701 ff_vk_exec_pool_free(&ev->s, &ev->exec_pool);
702
703 ff_vk_shader_free(&ev->s, &ev->shd_dct);
704 ff_vk_shader_free(&ev->s, &ev->shd_entropy[0]);
705 ff_vk_shader_free(&ev->s, &ev->shd_entropy[1]);
706 ff_vk_shader_free(&ev->s, &ev->shd_compact);
707
708 if (ev->exec_ctx_info) {
709 for (int i = 0; i < ev->async_depth; i++) {
715 }
717 }
718
723
724 ff_cbs_fragment_free(&ev->au);
725 ff_cbs_close(&ev->cbc);
726
728 ff_vk_uninit(&ev->s);
729
730 return 0;
731}
732
734{
735 int err;
737 AVHWFramesContext *hwfc;
738
739 if (!avctx->hw_frames_ctx) {
740 av_log(avctx, AV_LOG_ERROR, "An AVHWFramesContext is required.\n");
741 return AVERROR(EINVAL);
742 }
743 hwfc = (AVHWFramesContext *)avctx->hw_frames_ctx->data;
744 ev->sw_format = hwfc->sw_format;
745
748 if (ev->profile_idc < 0 || ev->chroma_format_idc < 0) {
749 av_log(avctx, AV_LOG_ERROR, "Unsupported sw_format %s for APV.\n",
751 return AVERROR(EINVAL);
752 }
753
754 /* All four APV chroma formats are supported -- 4:0:0, 4:2:2, 4:4:4 and
755 * 4:4:4:4. The profile_idc / chroma_format_idc checks above already
756 * reject any pixel format that is not one of them. */
758 ev->bit_depth = desc->comp[0].depth;
759 ev->num_comp = desc->nb_components;
760 ev->blocks_per_mb = 4; /* luma: 16x16 MB -> 4 8x8 blocks */
761 ev->chroma_blocks_per_mb = 4 >> (desc->log2_chroma_w + desc->log2_chroma_h);
762 ev->level_idc = 33; /* placeholder, real value depends on resolution and bitrate */
763 ev->band_idc = 0;
764
765 /* Frame dimensions in macroblocks */
766 ev->frame_mb_x = (avctx->width + APV_MB_WIDTH - 1) / APV_MB_WIDTH;
767 ev->frame_mb_y = (avctx->height + APV_MB_HEIGHT - 1) / APV_MB_HEIGHT;
768
769 /* The 20x20 tile grid cap is structural (fixed-size arrays everywhere);
770 * the spec additionally demands tiles of at least 16x8 MBs. Each
771 * tile-component maps to one entropy workgroup, one invocation per
772 * transform block. */
773 int grid_tw = (ev->frame_mb_x + APV_MAX_TILE_COLS - 1) / APV_MAX_TILE_COLS;
774 int grid_th = (ev->frame_mb_y + APV_MAX_TILE_ROWS - 1) / APV_MAX_TILE_ROWS;
775 int min_tw = FFMAX(APV_MIN_TILE_WIDTH_IN_MBS, grid_tw);
776 int min_th = FFMAX(APV_MIN_TILE_HEIGHT_IN_MBS, grid_th);
777
778 /* tile_w/tile_h pick the tile size in MBs; 0 selects the spec minimum.
779 * An explicit request below the spec minimum is honoured down to the
780 * grid cap -- non-conformant, but more tiles mean shorter (serial)
781 * entropy streams, which is the decode speed lever. */
782 ev->tile_mb_w = ev->tile_w_mbs_opt > 0 ? ev->tile_w_mbs_opt : min_tw;
783 ev->tile_mb_h = ev->tile_h_mbs_opt > 0 ? ev->tile_h_mbs_opt : min_th;
784 ev->tile_mb_w = FFMIN(FFMAX(ev->tile_mb_w, grid_tw), ev->frame_mb_x);
785 ev->tile_mb_h = FFMIN(FFMAX(ev->tile_mb_h, grid_th), ev->frame_mb_y);
788 av_log(avctx, AV_LOG_WARNING,
789 "Tile size %dx%d MBs is below the spec minimum of %dx%d: "
790 "NON-CONFORMANT bitstream, most decoders will reject it.\n",
791 ev->tile_mb_w, ev->tile_mb_h,
793
794 /* Left to default, grow the tile toward 1024 transform blocks (the
795 * entropy workgroup ceiling) while it still divides the frame. Bigger
796 * tiles mean fewer tile-components, which the compaction pass strongly
797 * prefers -- it is the dominant win for throughput. */
798 if (!ev->tile_w_mbs_opt && !ev->tile_h_mbs_opt) {
799 while (ev->tile_mb_w * 2 <= ev->frame_mb_x &&
800 ev->frame_mb_x % (ev->tile_mb_w * 2) == 0 &&
801 (ev->tile_mb_w * 2) * ev->tile_mb_h * ev->blocks_per_mb <= 1024)
802 ev->tile_mb_w *= 2;
803 while (ev->tile_mb_h * 2 <= ev->frame_mb_y &&
804 ev->frame_mb_y % (ev->tile_mb_h * 2) == 0 &&
805 ev->tile_mb_w * (ev->tile_mb_h * 2) * ev->blocks_per_mb <= 1024)
806 ev->tile_mb_h *= 2;
807 }
808
809 /* Ceil division: the rightmost column / bottom row of tiles take the
810 * remainder MBs (spec-legal; the tile grid is closed at the frame edge,
811 * so those tiles may be smaller than the signalled tile size). */
812 ev->tile_cols = (ev->frame_mb_x + ev->tile_mb_w - 1) / ev->tile_mb_w;
813 ev->tile_rows = (ev->frame_mb_y + ev->tile_mb_h - 1) / ev->tile_mb_h;
814 ev->tile_count = ev->tile_cols * ev->tile_rows;
815
816 if (ev->tile_count > APV_MAX_TILE_COUNT) {
817 av_log(avctx, AV_LOG_ERROR, "Too many tiles (%d).\n", ev->tile_count);
818 return AVERROR(EINVAL);
819 }
820
821 /* The entropy shader runs one invocation per block in a tile-component
822 * and its shared buffers are sized for 1024. */
823 if (ev->tile_mb_w * ev->tile_mb_h * ev->blocks_per_mb > 1024) {
824 av_log(avctx, AV_LOG_ERROR,
825 "Tile-component has too many transform blocks (%d > 1024).\n",
826 ev->tile_mb_w * ev->tile_mb_h * ev->blocks_per_mb);
828 }
829
830 /* qp_chroma left at 0 means "use the luma QP". */
831 if (ev->qp_c == 0)
832 ev->qp_c = ev->qp_y;
833
834 /* Validate QP range */
835 int max_qp = 3 + ev->bit_depth * 6;
836 if (ev->qp_y < 0 || ev->qp_y > max_qp || ev->qp_c < 0 || ev->qp_c > max_qp) {
837 av_log(avctx, AV_LOG_ERROR,
838 "QP out of range [0, %d]: qp_y=%d, qp_c=%d.\n",
839 max_qp, ev->qp_y, ev->qp_c);
840 return AVERROR(EINVAL);
841 }
842
843 /* Buffer sizing */
844 size_t blocks_per_tile = (size_t)ev->tile_mb_w * ev->tile_mb_h * ev->blocks_per_mb;
845 ev->coeffs_size = (size_t)ev->tile_count * ev->num_comp *
846 blocks_per_tile * APV_BLK_COEFFS * sizeof(int16_t);
847
848 /* Worst-case per-tile-component bytestream: each coefficient at most ~32 bits.
849 * Round up generously. */
850 ev->slot_size = blocks_per_tile * APV_BLK_COEFFS * 8;
851 ev->slot_size = FFALIGN(ev->slot_size, 64);
852 ev->bytestream_size = (size_t)ev->tile_count * ev->num_comp * ev->slot_size;
853 ev->sizes_size = ((size_t)ev->tile_count * ev->num_comp + 1) * sizeof(uint32_t);
854
855 av_log(avctx, AV_LOG_VERBOSE,
856 "APV Vulkan encoder: %dx%d, %d tiles (%dx%d MBs each), "
857 "qp_y=%d qp_c=%d, coeffs=%zu KiB, bytestream=%zu KiB\n",
858 avctx->width, avctx->height, ev->tile_count,
859 ev->tile_mb_w, ev->tile_mb_h, ev->qp_y, ev->qp_c,
860 ev->coeffs_size / 1024, ev->bytestream_size / 1024);
861
862 ev->headers_only = !!getenv("APV_VULKAN_HEADERS_ONLY");
863 ev->skip_entropy = !!getenv("APV_VULKAN_SKIP_ENTROPY");
864 if (ev->skip_entropy)
865 ev->headers_only = 1; /* the bitstream is never produced */
866 if (ev->headers_only)
867 av_log(avctx, AV_LOG_WARNING,
868 "APV_VULKAN_HEADERS_ONLY set: tiles will not be downloaded "
869 "or assembled; output packets contain headers only.\n");
870 if (ev->skip_entropy)
871 av_log(avctx, AV_LOG_WARNING,
872 "APV_VULKAN_SKIP_ENTROPY set: entropy dispatch skipped "
873 "(DCT-only benchmark mode).\n");
874
875 /* Init Vulkan */
876 err = ff_vk_init(&ev->s, avctx, NULL, avctx->hw_frames_ctx);
877 if (err < 0)
878 return err;
879
880 ev->qf = ff_vk_qf_find(&ev->s, VK_QUEUE_COMPUTE_BIT, 0);
881 if (!ev->qf) {
882 av_log(avctx, AV_LOG_ERROR, "Device has no compute queues!\n");
883 return AVERROR(ENOTSUP);
884 }
885
886 err = ff_vk_exec_pool_init(&ev->s, ev->qf, &ev->exec_pool,
887 ev->async_depth, 0, 0, 0, NULL);
888 if (err < 0)
889 return err;
890
891 /* Init CBS for assembling output */
892 err = ff_cbs_init(&ev->cbc, AV_CODEC_ID_APV, avctx);
893 if (err < 0)
894 return err;
895
896 /* Shaders */
897 err = init_dct_shader(avctx);
898 if (err < 0)
899 return err;
900 err = init_entropy_shader(avctx, ev->blocks_per_mb, &ev->shd_entropy[0]);
901 if (err < 0)
902 return err;
904 &ev->shd_entropy[1]);
905 if (err < 0)
906 return err;
907 err = ff_vk_seg_gather_init(&ev->s, &ev->exec_pool, &ev->shd_compact);
908 if (err < 0)
909 return err;
910
911 /* The DCT/quantize shader's push constants never change frame to frame;
912 * build them once. */
914
916 if (err < 0)
917 return err;
918
919 /* Async data pool */
921 ev->exec_ctx_info = av_calloc(ev->async_depth, sizeof(*ev->exec_ctx_info));
922 if (!ev->exec_ctx_info)
923 return AVERROR(ENOMEM);
924 for (int i = 0; i < ev->async_depth; i++)
926
927 return 0;
928}
929
930#define OFFSET(x) offsetof(VulkanEncodeAPVContext, x)
931#define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM
933 { "qp", "Quantization parameter (luma)", OFFSET(qp_y),
934 AV_OPT_TYPE_INT, { .i64 = 22 }, 0, 255, VE },
935 { "qp_chroma", "Chroma quantization parameter (0 = same as luma qp)", OFFSET(qp_c),
936 AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 255, VE },
937 { "qmatrix", "Quantization matrix", OFFSET(qmatrix),
938 AV_OPT_TYPE_INT, { .i64 = APV_QMATRIX_HEVC }, 0, 1, VE, "qmatrix" },
939 { "flat", "Uniform matrix, all 16 (APV spec default)", 0,
940 AV_OPT_TYPE_CONST, { .i64 = APV_QMATRIX_FLAT }, 0, 0, VE, "qmatrix" },
941 { "hevc", "HEVC default intra scaling list (mild perceptual shaping)", 0,
942 AV_OPT_TYPE_CONST, { .i64 = APV_QMATRIX_HEVC }, 0, 0, VE, "qmatrix" },
943 /* The minimum legal tile is 16x8 MBs; the maxima are this encoder's
944 * ceiling of 1024 transform blocks per tile-component (256 MBs): with
945 * the other dimension at its minimum, width <= 32 and height <= 16. A
946 * value of 0 is the sentinel for the adaptive per-frame default. */
947 { "tile_width", "Tile width in macroblocks (0 = adaptive, auto-sized per frame)", OFFSET(tile_w_mbs_opt),
948 AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 32, VE },
949 { "tile_height", "Tile height in macroblocks (0 = adaptive, auto-sized per frame)", OFFSET(tile_h_mbs_opt),
950 AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 16, VE },
951 { "async_depth", "Internal parallelization depth", OFFSET(async_depth),
952 AV_OPT_TYPE_INT, { .i64 = 1 }, 1, INT_MAX, VE },
953 { NULL }
954};
955
957 { "g", "1" },
958 { NULL },
959};
960
962 .class_name = "apv_vulkan",
963 .item_name = av_default_item_name,
965 .version = LIBAVUTIL_VERSION_INT,
966};
967
969 HW_CONFIG_ENCODER_FRAMES(VULKAN, VULKAN),
970 NULL,
971};
972
974 .p.name = "apv_vulkan",
975 CODEC_LONG_NAME("Advanced Professional Video (Vulkan)"),
976 .p.type = AVMEDIA_TYPE_VIDEO,
977 .p.id = AV_CODEC_ID_APV,
978 .priv_data_size = sizeof(VulkanEncodeAPVContext),
981 .flush = &vulkan_encode_apv_flush,
982 .close = &vulkan_encode_apv_close,
983 .p.priv_class = &vulkan_encode_apv_class,
984 .p.capabilities = AV_CODEC_CAP_DELAY |
989 .caps_internal = FF_CODEC_CAP_INIT_CLEANUP,
990 .defaults = vulkan_encode_apv_defaults,
992 .hw_configs = vulkan_encode_apv_hw_configs,
993 .p.wrapper_name = "vulkan",
994};
static double fact(double i)
Definition af_aiir.c:936
const FFCodec ff_apv_vulkan_encoder
#define VE
Definition amfenc_av1.c:30
const unsigned int ff_apv_encode_dct_comp_spv_len
static int build_packet(AVCodecContext *avctx, FFVkExecContext *exec, AVPacket *pkt)
const unsigned char ff_apv_encode_tiles_comp_spv_data[]
static av_cold void vulkan_encode_apv_flush(AVCodecContext *avctx)
static int vulkan_encode_apv_receive_packet(AVCodecContext *avctx, AVPacket *pkt)
static const uint8_t apv_qmat_hevc_intra[64]
static av_cold int vulkan_encode_apv_init(AVCodecContext *avctx)
static const AVCodecHWConfigInternal *const vulkan_encode_apv_hw_configs[]
const unsigned char ff_apv_encode_dct_comp_spv_data[]
static const uint8_t apv_level_scale[6]
static int init_dct_shader(AVCodecContext *avctx)
static int init_entropy_shader(AVCodecContext *avctx, int blocks_per_mb, FFVulkanShader *shd)
@ APV_QMATRIX_FLAT
@ APV_QMATRIX_HEVC
static const AVClass vulkan_encode_apv_class
#define APV_DEFAULT_QMAT
static av_cold int vulkan_encode_apv_close(AVCodecContext *avctx)
static void build_dct_push_const(AVCodecContext *avctx)
static const AVOption vulkan_encode_apv_options[]
static const FFCodecDefault vulkan_encode_apv_defaults[]
static int profile_idc_from_pix_fmt(enum AVPixelFormat sw_fmt)
#define OFFSET(x)
static int chroma_format_from_pix_fmt(enum AVPixelFormat sw_fmt)
static int submit_frame(AVCodecContext *avctx, FFVkExecContext *exec, AVFrame *frame)
#define APV_MAX_NUM_COMP
static int apv_qmatrix_value(int qmatrix, int i)
const unsigned int ff_apv_encode_tiles_comp_spv_len
Libavcodec external API header.
static int FUNC tile(CodedBitstreamContext *ctx, RWContext *rw, APVRawTile *current, int tile_idx, uint32_t tile_size)
#define i(width, name, range_min, range_max)
Definition cbs_h264.c:63
#define CODEC_PIXFMTS(...)
#define FF_CODEC_RECEIVE_PACKET_CB(func)
#define CODEC_LONG_NAME(str)
#define FF_CODEC_CAP_INIT_CLEANUP
The codec allows calling the close function for deallocation even if the init function returned a fai...
#define NULL
Definition coverity.c:32
static AVPacket * pkt
static AVFrame * frame
int(* init)(AVBSFContext *ctx)
Definition dts2pts.c:608
#define AV_NUM_DATA_POINTERS
Definition frame.h:473
#define fail
Definition test.h:479
@ AV_OPT_TYPE_CONST
Special option type for declaring named constants.
Definition opt.h:298
@ AV_OPT_TYPE_INT
Underlying C type is int.
Definition opt.h:258
#define AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE
This encoder can reorder user opaque values from input AVFrames and return them with corresponding ou...
Definition codec.h:147
#define AV_CODEC_CAP_ENCODER_FLUSH
This encoder can be flushed using avcodec_flush_buffers().
Definition codec.h:154
#define AV_CODEC_CAP_DELAY
Encoder or decoder requires flushing with NULL input at the end in order to give the complete and cor...
Definition codec.h:79
#define AV_CODEC_CAP_DR1
Codec uses get_buffer() or get_encode_buffer() for allocating buffers and supports custom allocators.
Definition codec.h:49
#define AV_CODEC_CAP_HARDWARE
Codec is backed by a hardware implementation.
Definition codec.h:133
@ AV_CODEC_ID_APV
Definition codec_id.h:323
#define AVERROR_PATCHWELCOME
Not yet implemented in FFmpeg, patches welcome.
Definition error.h:64
#define AVERROR(e)
Definition error.h:45
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition log.h:216
#define AV_LOG_VERBOSE
Detailed information.
Definition log.h:226
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition log.h:210
const char * av_default_item_name(void *ptr)
Return the context name.
Definition log.c:241
@ AVMEDIA_TYPE_VIDEO
Definition avutil.h:200
#define LIBAVUTIL_VERSION_INT
Definition version.h:85
#define HW_CONFIG_ENCODER_FRAMES(format, device_type_)
Definition hwconfig.h:100
static const int sizes[][2]
Definition img2dec.c:62
#define r
Definition input.c:42
static const int level_scale[2][6]
Definition intra.c:336
@ APV_PBU_PRIMARY_FRAME
Definition apv.h:27
@ APV_CHROMA_FORMAT_422
Definition apv.h:48
@ APV_CHROMA_FORMAT_400
Definition apv.h:47
@ APV_CHROMA_FORMAT_4444
Definition apv.h:50
@ APV_CHROMA_FORMAT_444
Definition apv.h:49
@ APV_MB_HEIGHT
Definition apv.h:41
@ APV_MB_WIDTH
Definition apv.h:40
@ APV_MIN_TILE_WIDTH_IN_MBS
Definition apv.h:73
@ APV_MAX_TILE_COUNT
Definition apv.h:77
@ APV_MAX_TILE_COLS
Definition apv.h:75
@ APV_MIN_TILE_HEIGHT_IN_MBS
Definition apv.h:74
@ APV_MAX_TILE_ROWS
Definition apv.h:76
@ APV_PROFILE_4444_12
Definition apv.h:67
@ APV_PROFILE_444_10
Definition apv.h:64
@ APV_PROFILE_400_10
Definition apv.h:68
@ APV_PROFILE_422_10
Definition apv.h:62
@ APV_PROFILE_422_12
Definition apv.h:63
@ APV_PROFILE_4444_10
Definition apv.h:66
@ APV_PROFILE_444_12
Definition apv.h:65
@ APV_BLK_COEFFS
Definition apv.h:55
common internal api header.
#define av_cold
Definition attributes.h:117
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:2690
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:2262
void ff_vk_shader_add_descriptor_set(FFVulkanContext *s, FFVulkanShader *shd, const FFVulkanDescriptorSetBinding *desc, int nb, int singular)
Add descriptor to a shader.
Definition vulkan.c:2521
void ff_vk_exec_pool_free(FFVulkanContext *s, FFVkExecPool *pool)
Definition vulkan.c:335
int ff_vk_exec_pool_init(FFVulkanContext *s, AVVulkanDeviceQueueFamily *qf, FFVkExecPool *pool, int nb_contexts, int nb_queries, VkQueryType query_type, int query_64bit, const void *query_create_pnext)
Allocates/frees an execution pool.
Definition vulkan.c:399
void ff_vk_exec_wait(FFVulkanContext *s, FFVkExecContext *e)
Definition vulkan.c:649
int ff_vk_shader_add_push_const(FFVulkanShader *shd, int offset, int size, VkShaderStageFlagBits stage)
Add/update push constants for execution.
Definition vulkan.c:1631
void ff_vk_uninit(FFVulkanContext *s)
Frees main context.
Definition vulkan.c:2779
int ff_vk_init(FFVulkanContext *s, void *log_parent, AVBufferRef *device_ref, AVBufferRef *frames_ref)
Initializes the AVClass, in case this context is not used as the main user's context.
Definition vulkan.c:2795
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:2216
int ff_vk_exec_start(FFVulkanContext *s, FFVkExecContext *e)
Start/submit/wait an execution.
Definition vulkan.c:664
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:2147
void ff_vk_shader_free(FFVulkanContext *s, FFVulkanShader *shd)
Free a shader.
Definition vulkan.c:2757
int ff_vk_shader_register_exec(FFVulkanContext *s, FFVkExecPool *pool, FFVulkanShader *shd)
Register a shader with an exec pool.
Definition vulkan.c:2555
int ff_vk_exec_submit(FFVulkanContext *s, FFVkExecContext *e)
Definition vulkan.c:987
void ff_vk_exec_bind_shader(FFVulkanContext *s, FFVkExecContext *e, const FFVulkanShader *shd)
Bind a shader.
Definition vulkan.c:2739
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:2703
AVVulkanDeviceQueueFamily * ff_vk_qf_find(FFVulkanContext *s, VkQueueFlagBits dev_family, VkVideoCodecOperationFlagBitsKHR vid_ops)
Chooses an appropriate QF.
Definition vulkan.c:320
void ff_vk_exec_add_dep_refstruct(FFVulkanContext *s, FFVkExecContext *e, void *obj)
Execution dependency management.
Definition vulkan.c:783
int ff_vk_get_pooled_buffer(FFVulkanContext *ctx, AVRefStructPool **buf_pool, FFVkBuffer **buf, VkBufferUsageFlags usage, void *create_pNext, size_t size, VkMemoryPropertyFlagBits mem_props)
Initialize a pool and create AVBufferRefs containing FFVkBuffer.
Definition vulkan.c:1444
void ff_vk_exec_discard(FFVulkanContext *s, FFVkExecContext *e)
Definition vulkan.c:767
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:2425
int ff_vk_exec_add_dep_frame(FFVulkanContext *s, FFVkExecContext *e, AVFrame *f, VkPipelineStageFlagBits2 wait_stage, VkPipelineStageFlagBits2 signal_stage)
Definition vulkan.c:885
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:2729
const char * desc
Definition libsvtav1.c:83
#define FFMIN(a, b)
Definition macros.h:49
#define FFMAX(a, b)
Definition macros.h:47
#define FFALIGN(x, a)
Definition macros.h:78
void * av_calloc(size_t nmemb, size_t size)
Definition mem.c:370
Memory handling functions.
AVOptions.
int av_pix_fmt_count_planes(enum AVPixelFormat pix_fmt)
Definition pixdesc.c:3500
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:3380
const AVPixFmtDescriptor * av_pix_fmt_desc_get(enum AVPixelFormat pix_fmt)
Definition pixdesc.c:3460
#define AV_PIX_FMT_YUV444P12
Definition pixfmt.h:552
AVColorRange
Visual content value range.
Definition pixfmt.h:748
@ AVCOL_RANGE_JPEG
Full range content.
Definition pixfmt.h:783
#define AV_PIX_FMT_YUVA444P10
Definition pixfmt.h:598
#define AV_PIX_FMT_YUV422P12
Definition pixfmt.h:550
#define AV_PIX_FMT_YUV422P10
Definition pixfmt.h:546
#define AV_PIX_FMT_GRAY12
Definition pixfmt.h:526
AVPixelFormat
Pixel format.
Definition pixfmt.h:71
@ AV_PIX_FMT_VULKAN
Vulkan hardware images.
Definition pixfmt.h:379
#define AV_PIX_FMT_GRAY10
Definition pixfmt.h:525
AVColorPrimaries
Chromaticity coordinates of the source primaries.
Definition pixfmt.h:642
@ AVCOL_PRI_UNSPECIFIED
Definition pixfmt.h:645
AVColorTransferCharacteristic
Color Transfer Characteristic.
Definition pixfmt.h:672
@ AVCOL_TRC_UNSPECIFIED
Definition pixfmt.h:675
#define AV_PIX_FMT_YUVA444P12
Definition pixfmt.h:600
#define AV_PIX_FMT_YUV444P10
Definition pixfmt.h:548
AVColorSpace
YUV colorspace type.
Definition pixfmt.h:706
@ AVCOL_SPC_UNSPECIFIED
Definition pixfmt.h:709
void av_refstruct_unref(void *objp)
Decrement the reference count of the underlying object and automatically free the object if there are...
Definition refstruct.c:121
static void av_refstruct_pool_uninit(AVRefStructPool **poolp)
Mark the pool as being available for freeing.
Definition refstruct.h:292
APVRawTileInfo tile_info
Definition cbs_apv.h:80
uint8_t color_primaries
Definition cbs_apv.h:72
uint8_t color_description_present_flag
Definition cbs_apv.h:71
APVRawFrameInfo frame_info
Definition cbs_apv.h:68
APVRawQuantizationMatrix quantization_matrix
Definition cbs_apv.h:78
uint8_t full_range_flag
Definition cbs_apv.h:75
uint8_t matrix_coefficients
Definition cbs_apv.h:74
uint8_t transfer_characteristics
Definition cbs_apv.h:73
uint8_t use_q_matrix
Definition cbs_apv.h:77
uint8_t level_idc
Definition cbs_apv.h:45
uint32_t frame_width
Definition cbs_apv.h:48
uint8_t band_idc
Definition cbs_apv.h:46
uint8_t bit_depth_minus8
Definition cbs_apv.h:51
uint8_t profile_idc
Definition cbs_apv.h:44
uint32_t frame_height
Definition cbs_apv.h:49
uint8_t chroma_format_idc
Definition cbs_apv.h:50
uint8_t capture_time_distance
Definition cbs_apv.h:52
APVRawFrameHeader frame_header
Definition cbs_apv.h:103
APVRawTile tile[APV_MAX_TILE_COUNT]
Definition cbs_apv.h:105
APVRawPBUHeader pbu_header
Definition cbs_apv.h:102
uint32_t tile_size[APV_MAX_TILE_COUNT]
Definition cbs_apv.h:104
uint8_t pbu_type
Definition cbs_apv.h:34
uint16_t group_id
Definition cbs_apv.h:35
uint8_t q_matrix[APV_MAX_NUM_COMP][APV_TR_SIZE][APV_TR_SIZE]
Definition cbs_apv.h:57
uint32_t tile_width_in_mbs
Definition cbs_apv.h:61
uint32_t tile_height_in_mbs
Definition cbs_apv.h:62
uint8_t tile_size_present_in_fh_flag
Definition cbs_apv.h:63
uint8_t * data
The data buffer.
Definition buffer.h:90
Describe the class of an AVClass context structure.
Definition log.h:76
main external API structure.
Definition avcodec.h:443
int width
picture width / height.
Definition avcodec.h:604
AVBufferRef * hw_frames_ctx
A reference to the AVHWFramesContext describing the input (for encoding) or output (decoding) frames.
Definition avcodec.h:1472
void * priv_data
Definition avcodec.h:470
This structure describes decoded (raw) audio or video data.
Definition frame.h:472
This struct describes a set or pool of "hardware" frames (i.e.
Definition hwcontext.h:118
enum AVPixelFormat sw_format
The pixel format identifying the actual data layout of the hardware frames.
Definition hwcontext.h:213
AVOption.
Definition opt.h:428
This structure stores compressed data.
Definition packet.h:580
Descriptor that unambiguously describes how the bits of a pixel are stored in the up to 4 data planes...
Definition pixdesc.h:69
AVRefStructPool is an API for a thread-safe pool of objects managed via the RefStruct API.
Definition refstruct.c:184
VkDevice act_dev
Active device.
Context structure for coded bitstream operations.
Definition cbs.h:226
Coded bitstream fragment structure, combining one or more units.
Definition cbs.h:129
float qf[APV_MAX_NUM_COMP]
uint8_t qmat[64]
VkDeviceAddress bytestream
VkDeviceAddress address
Definition vulkan.h:99
size_t size
Definition vulkan.h:98
VkMemoryPropertyFlagBits flags
Definition vulkan.h:97
VkDeviceMemory mem
Definition vulkan.h:96
uint8_t * mapped_mem
Definition vulkan.h:103
Frame loop for compute encoders.
void * opaque
Definition vulkan.h:154
VkCommandBuffer buf
Definition vulkan.h:142
FFVkExecContext * contexts
Definition vulkan.h:271
int pool_size
Definition vulkan.h:276
AVVulkanDeviceContext * hwctx
Definition vulkan.h:340
VkPhysicalDeviceSubgroupSizeControlProperties subgroup_props
Definition vulkan.h:304
FFVulkanFunctions vkfn
Definition vulkan.h:296
CodedBitstreamContext * cbc
AVRefStructPool * coeffs_pool
CodedBitstreamFragment au
AVVulkanDeviceQueueFamily * qf
AVRefStructPool * sizes_pool
FFVulkanShader shd_entropy[2]
AVRefStructPool * compacted_pool
enum AVPixelFormat sw_format
VulkanEncodeAPVFrameData * exec_ctx_info
AVRefStructPool * bytestream_pool
enum AVColorTransferCharacteristic color_trc
enum AVColorPrimaries color_primaries
enum AVColorRange color_range
enum AVColorSpace colorspace
#define av_freep(p)
#define av_log(a,...)
#define NONE
Definition vf_drawvg.c:262
static double c[64]
#define ff_vk_buf_barrier(dst, vkb, s_stage, s_access, s_access2, d_stage, d_access, d_access2, offs, bsz)
Definition vulkan.h:579
@ FF_VK_REP_INT
Definition vulkan.h:444
#define RET(x)
Definition vulkan.h:37
#define SPEC_LIST_ADD(name, idx, val_bits, val)
Definition vulkan.h:55
#define SPEC_LIST_CREATE(name, max_length, max_size)
Definition vulkan.h:45
int ff_vk_encode_loop_receive_packet(AVCodecContext *avctx, FFVkEncodeLoop *l, AVPacket *pkt)
Call from FFCodec.cb.receive_packet; the packet metadata is carried from the submitted frame to its p...
void ff_vk_encode_loop_uninit(FFVkEncodeLoop *l)
void ff_vk_encode_loop_flush(AVCodecContext *avctx, FFVkEncodeLoop *l)
Waits for and discards every frame in flight.
int ff_vk_encode_loop_init(FFVulkanContext *s, FFVkExecPool *pool, FFVkEncodeLoop *l, int(*submit_frame)(AVCodecContext *avctx, FFVkExecContext *exec, AVFrame *frame), int(*get_packet)(AVCodecContext *avctx, FFVkExecContext *exec, AVPacket *pkt))
int ff_vk_seg_gather_init(FFVulkanContext *s, FFVkExecPool *pool, FFVulkanShader *shd)
Packs fixed-stride segment slots back to back into a contiguous buffer.
int ff_vk_seg_gather(FFVulkanContext *s, FFVkExecContext *exec, FFVulkanShader *shd, FFVkBuffer *sizes, size_t sizes_offset, uint32_t nb_segs, FFVkBuffer *sparse, uint32_t slot_size, FFVkBuffer *compacted, size_t compacted_offset, VkDeviceAddress offset_addr)
Gathers nb_segs slots of slot_size bytes from sparse into compacted, with the segment sizes given as ...