FFmpeg
Loading...
Searching...
No Matches
proresenc_kostya_vulkan.c
Go to the documentation of this file.
1/*
2 * Apple ProRes encoder
3 *
4 * Copyright (c) 2011 Anatoliy Wasserman
5 * Copyright (c) 2012 Konstantin Shishkov
6 *
7 * This file is part of FFmpeg.
8 *
9 * FFmpeg is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
13 *
14 * FFmpeg is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with FFmpeg; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 */
23
24#include "libavutil/avassert.h"
25#include "libavutil/buffer.h"
26#include "libavutil/macros.h"
27#include "libavutil/mem.h"
29#include "libavutil/opt.h"
30#include "libavutil/pixdesc.h"
33#include "libavutil/vulkan.h"
34#include "avcodec.h"
35#include "codec.h"
36#include "codec_internal.h"
37#include "encode.h"
38#include "packet.h"
39#include "put_bits.h"
40#include "profiles.h"
41#include "bytestream.h"
42#include "proresdata.h"
44#include "hwconfig.h"
45#include "vulkan_video.h"
46
47#define DCTSIZE 8
48
49typedef struct ProresDataTables {
50 int16_t qmat[128][64];
51 int16_t qmat_chroma[128][64];
53
59
60typedef struct EncodeSliceInfo {
61 VkDeviceAddress bytestream;
62 VkDeviceAddress slice_sizes;
63 uint32_t slot_size;
65
66typedef struct SliceData {
67 uint32_t mbs_per_slice;
69} SliceData;
70
79
94
126
127extern const unsigned char ff_prores_ks_alpha_data_comp_spv_data[];
128extern const unsigned int ff_prores_ks_alpha_data_comp_spv_len;
129
130extern const unsigned char ff_prores_ks_slice_data_comp_spv_data[];
131extern const unsigned int ff_prores_ks_slice_data_comp_spv_len;
132
133extern const unsigned char ff_prores_ks_estimate_slice_comp_spv_data[];
134extern const unsigned int ff_prores_ks_estimate_slice_comp_spv_len;
135
136extern const unsigned char ff_prores_ks_trellis_node_comp_spv_data[];
137extern const unsigned int ff_prores_ks_trellis_node_comp_spv_len;
138
139extern const unsigned char ff_prores_ks_encode_slice_comp_spv_data[];
140extern const unsigned int ff_prores_ks_encode_slice_comp_spv_len;
141
142static int init_slice_data_pipeline(ProresVulkanContext *pv, FFVulkanShader *shd, int blocks_per_mb)
143{
144 int err = 0;
145 FFVulkanContext *vkctx = &pv->vkctx;
147
148 SPEC_LIST_CREATE(sl, 5, 5 * sizeof(uint32_t))
149 SPEC_LIST_ADD(sl, 0, 32, pv->ctx.mbs_per_slice);
150 SPEC_LIST_ADD(sl, 1, 32, blocks_per_mb);
151 SPEC_LIST_ADD(sl, 2, 32, pv->ctx.mb_width);
152 SPEC_LIST_ADD(sl, 3, 32, pv->ctx.pictures_per_frame);
153 SPEC_LIST_ADD(sl, 16, 32, blocks_per_mb * pv->ctx.mbs_per_slice); /* nb_blocks */
154
155 ff_vk_shader_load(shd, VK_SHADER_STAGE_COMPUTE_BIT, sl,
156 (uint32_t []) { DCTSIZE, blocks_per_mb, pv->ctx.mbs_per_slice }, 0);
157
159 {
160 .name = "SliceBuffer",
161 .type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
162 .stages = VK_SHADER_STAGE_COMPUTE_BIT,
163 },
164 {
165 .name = "planes",
166 .type = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
167 .stages = VK_SHADER_STAGE_COMPUTE_BIT,
168 .elems = av_pix_fmt_count_planes(vkctx->frames->sw_format),
169 },
170 };
171 ff_vk_shader_add_descriptor_set(vkctx, shd, desc, 2, 0);
172
173 ff_vk_shader_add_push_const(shd, 0, sizeof(SliceDataInfo), VK_SHADER_STAGE_COMPUTE_BIT);
174
175 RET(ff_vk_shader_link(vkctx, shd,
178
179 RET(ff_vk_shader_register_exec(vkctx, &pv->e, shd));
180
181fail:
182 return err;
183}
184
186{
187 int err = 0;
188 FFVulkanContext *vkctx = &pv->vkctx;
190
191 SPEC_LIST_CREATE(sl, 4, 4 * sizeof(uint32_t))
192 SPEC_LIST_ADD(sl, 0, 32, pv->ctx.alpha_bits);
193 SPEC_LIST_ADD(sl, 1, 32, pv->ctx.slices_width);
194 SPEC_LIST_ADD(sl, 2, 32, pv->ctx.mb_width);
195 SPEC_LIST_ADD(sl, 3, 32, pv->ctx.mbs_per_slice);
196
197 ff_vk_shader_load(shd, VK_SHADER_STAGE_COMPUTE_BIT, sl,
198 (uint32_t []) { 16, 16, 1 }, 0);
199
201 {
202 .name = "SliceBuffer",
203 .type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
204 .stages = VK_SHADER_STAGE_COMPUTE_BIT,
205 },
206 {
207 .name = "plane",
208 .type = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
209 .stages = VK_SHADER_STAGE_COMPUTE_BIT,
210 },
211 };
212 ff_vk_shader_add_descriptor_set(vkctx, shd, desc, 2, 0);
213
214 RET(ff_vk_shader_link(vkctx, shd,
217
218 RET(ff_vk_shader_register_exec(vkctx, &pv->e, shd));
219
220fail:
221 return err;
222}
223
225{
226 int err = 0;
227 FFVulkanContext *vkctx = &pv->vkctx;
229 /* A single subgroup per workgroup, pinned to its size where possible */
230 int required = vkctx->subgroup_props.requiredSubgroupSizeStages &
231 VK_SHADER_STAGE_COMPUTE_BIT;
232 int dim_x = required ? vkctx->subgroup_props.maxSubgroupSize :
233 vkctx->subgroup_props.minSubgroupSize;
234
235 pv->estimate_slices_per_wg = dim_x / pv->ctx.num_planes;
236
237 SPEC_LIST_CREATE(sl, 9, 9 * sizeof(uint32_t))
238 SPEC_LIST_ADD(sl, 0, 32, pv->ctx.mbs_per_slice);
239 SPEC_LIST_ADD(sl, 1, 32, pv->ctx.chroma_factor);
240 SPEC_LIST_ADD(sl, 2, 32, pv->ctx.alpha_bits);
241 SPEC_LIST_ADD(sl, 3, 32, pv->ctx.num_planes);
242 SPEC_LIST_ADD(sl, 4, 32, pv->ctx.slices_per_picture);
243 SPEC_LIST_ADD(sl, 5, 32, pv->ctx.force_quant ? 0 : pv->ctx.profile_info->min_quant);
244 SPEC_LIST_ADD(sl, 6, 32, pv->ctx.force_quant ? 0 : pv->ctx.profile_info->max_quant);
245 SPEC_LIST_ADD(sl, 7, 32, pv->ctx.bits_per_mb);
246 SPEC_LIST_ADD(sl, 8, 32, pv->ctx.force_quant);
247
248 ff_vk_shader_load(shd, VK_SHADER_STAGE_COMPUTE_BIT, sl,
249 (uint32_t []) { dim_x, 1, 1 }, required ? dim_x : 0);
250
252 {
253 .name = "SliceBuffer",
254 .type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
255 .stages = VK_SHADER_STAGE_COMPUTE_BIT,
256 },
257 {
258 .name = "SliceScores",
259 .type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
260 .stages = VK_SHADER_STAGE_COMPUTE_BIT,
261 },
262 {
263 .name = "ProresDataTables",
264 .type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
265 .stages = VK_SHADER_STAGE_COMPUTE_BIT,
266 },
267 };
268 ff_vk_shader_add_descriptor_set(vkctx, shd, desc, 3, 0);
269
270 RET(ff_vk_shader_link(vkctx, shd,
273 RET(ff_vk_shader_register_exec(vkctx, &pv->e, shd));
274
275fail:
276 return err;
277}
278
280{
281 int err = 0;
282 FFVulkanContext *vkctx = &pv->vkctx;
284
285 SPEC_LIST_CREATE(sl, 7, 7 * sizeof(uint32_t))
286 SPEC_LIST_ADD(sl, 0, 32, pv->ctx.slices_width);
287 SPEC_LIST_ADD(sl, 2, 32, pv->ctx.num_planes);
288 SPEC_LIST_ADD(sl, 3, 32, pv->ctx.force_quant);
289 SPEC_LIST_ADD(sl, 4, 32, pv->ctx.profile_info->min_quant);
290 SPEC_LIST_ADD(sl, 5, 32, pv->ctx.profile_info->max_quant);
291 SPEC_LIST_ADD(sl, 6, 32, pv->ctx.mbs_per_slice);
292 SPEC_LIST_ADD(sl, 7, 32, pv->ctx.bits_per_mb);
293
294 ff_vk_shader_load(shd, VK_SHADER_STAGE_COMPUTE_BIT, sl,
295 (uint32_t []) { pv->ctx.mb_height, 1, 1 }, 0);
296
298 {
299 .name = "SliceScores",
300 .type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
301 .stages = VK_SHADER_STAGE_COMPUTE_BIT,
302 },
303 };
304 ff_vk_shader_add_descriptor_set(vkctx, shd, desc, 1, 0);
305
306 RET(ff_vk_shader_link(vkctx, shd,
309
310 RET(ff_vk_shader_register_exec(vkctx, &pv->e, shd));
311
312fail:
313 return err;
314}
315
317{
318 int err = 0;
319 FFVulkanContext *vkctx = &pv->vkctx;
321
322 SPEC_LIST_CREATE(sl, 7, 7 * sizeof(uint32_t))
323 SPEC_LIST_ADD(sl, 0, 32, pv->ctx.mbs_per_slice);
324 SPEC_LIST_ADD(sl, 1, 32, pv->ctx.chroma_factor);
325 SPEC_LIST_ADD(sl, 2, 32, pv->ctx.alpha_bits);
326 SPEC_LIST_ADD(sl, 3, 32, pv->ctx.num_planes);
327 SPEC_LIST_ADD(sl, 4, 32, pv->ctx.slices_per_picture);
328 SPEC_LIST_ADD(sl, 5, 32, pv->ctx.profile_info->max_quant);
329 SPEC_LIST_ADD(sl, 6, 32, pv->ctx.force_quant);
330
331 ff_vk_shader_load(shd, VK_SHADER_STAGE_COMPUTE_BIT, sl,
332 (uint32_t []) { 64, 1, 1 }, 0);
333
335 {
336 .name = "SliceBuffer",
337 .type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
338 .stages = VK_SHADER_STAGE_COMPUTE_BIT,
339 },
340 {
341 .name = "SliceScores",
342 .type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
343 .stages = VK_SHADER_STAGE_COMPUTE_BIT,
344 },
345 {
346 .name = "ProresDataTables",
347 .type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
348 .stages = VK_SHADER_STAGE_COMPUTE_BIT,
349 },
350 };
351 ff_vk_shader_add_descriptor_set(vkctx, shd, desc, 3, 0);
352
353 ff_vk_shader_add_push_const(shd, 0, sizeof(EncodeSliceInfo), VK_SHADER_STAGE_COMPUTE_BIT);
354
355 RET(ff_vk_shader_link(vkctx, shd,
358
359 RET(ff_vk_shader_register_exec(vkctx, &pv->e, shd));
360
361fail:
362 return err;
363}
364
366 AVFrame *frame, int picture_idx)
367{
368 ProresVulkanContext *pv = avctx->priv_data;
369 ProresContext *ctx = &pv->ctx;
371 FFVulkanContext *vkctx = &pv->vkctx;
372 FFVulkanFunctions *vk = &vkctx->vkfn;
373 int err = 0, nb_img_bar = 0, i, is_chroma;
374 int min_quant = ctx->profile_info->min_quant;
375 int max_quant = ctx->profile_info->max_quant;
377 VkImageView views[AV_NUM_DATA_POINTERS];
378 VkImageMemoryBarrier2 img_bar[AV_NUM_DATA_POINTERS];
379 FFVkBuffer *pkt_vk_buf, *slice_data_buf, *slice_score_buf;
380 SliceDataInfo slice_data_info;
381 EncodeSliceInfo encode_info;
382 FFVulkanShader *shd;
383
384 /* Sparse slice output: one fixed-stride, device-local slot per slice */
385 RET(ff_vk_get_pooled_buffer(vkctx, &pv->pkt_buf_pool, &pd->out_data_ref[picture_idx],
386 VK_BUFFER_USAGE_STORAGE_BUFFER_BIT |
387 VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT, NULL,
388 ctx->slices_per_picture * pv->slice_slot_size,
389 VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT));
390 pkt_vk_buf = pd->out_data_ref[picture_idx];
391 ff_vk_exec_add_dep_refstruct(vkctx, exec, pd->out_data_ref[picture_idx]);
392
393 /* Per-slice sizes: read by the gather pass, and by the CPU to write the
394 * seek table. */
396 VK_BUFFER_USAGE_STORAGE_BUFFER_BIT |
397 VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT, NULL,
398 (ctx->slices_per_picture + 1) * sizeof(uint32_t),
399 VK_MEMORY_PROPERTY_HOST_CACHED_BIT |
400 VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
401 VK_MEMORY_PROPERTY_HOST_COHERENT_BIT));
402 ff_vk_exec_add_dep_refstruct(vkctx, exec, pd->slice_sizes_ref[picture_idx]);
403
404 /* Both pictures are gathered directly into the packet buffer */
405 if (!picture_idx) {
407 VK_BUFFER_USAGE_STORAGE_BUFFER_BIT |
408 VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT, NULL,
409 ctx->frame_size_upper_bound + FF_INPUT_BUFFER_MIN_SIZE,
410 VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
411 vkctx->host_cached_flag));
413 }
414
415 /* Allocate buffer for writing slice data */
416 RET(ff_vk_get_pooled_buffer(vkctx, &pv->slice_data_buf_pool, &pd->slice_data_ref[picture_idx],
417 VK_BUFFER_USAGE_STORAGE_BUFFER_BIT |
418 VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT, NULL,
419 ctx->slices_per_picture * sizeof(SliceData),
420 VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT));
421 slice_data_buf = pd->slice_data_ref[picture_idx];
422 ff_vk_exec_add_dep_refstruct(vkctx, exec, pd->slice_data_ref[picture_idx]);
423
424 /* Allocate buffer for writing slice scores */
426 VK_BUFFER_USAGE_STORAGE_BUFFER_BIT |
427 VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT, NULL,
428 ctx->slices_per_picture * sizeof(SliceScore),
429 VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT));
430 slice_score_buf = pd->slice_score_ref[picture_idx];
431 ff_vk_exec_add_dep_refstruct(vkctx, exec, pd->slice_score_ref[picture_idx]);
432
433 /* Generate barriers and image views for frame images. */
435 VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
436 VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT));
437 RET(ff_vk_create_imageviews(vkctx, exec, views, frame, FF_VK_REP_INT));
438 ff_vk_frame_barrier(vkctx, exec, frame, img_bar, &nb_img_bar,
439 VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
440 VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT,
441 VK_ACCESS_SHADER_READ_BIT,
442 VK_IMAGE_LAYOUT_GENERAL,
443 VK_QUEUE_FAMILY_IGNORED);
444
445 /* Submit the image barriers. */
446 vk->CmdPipelineBarrier2(exec->buf, &(VkDependencyInfo) {
447 .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
448 .pImageMemoryBarriers = img_bar,
449 .imageMemoryBarrierCount = nb_img_bar,
450 });
451
452 /* Apply FDCT on input image data for future passes */
453 slice_data_info = (SliceDataInfo) {
454 .line_add = ctx->pictures_per_frame == 1 ? 0 : picture_idx ^ !(frame->flags & AV_FRAME_FLAG_TOP_FIELD_FIRST),
455 };
456 for (i = 0; i < ctx->num_planes; i++) {
457 is_chroma = (i == 1 || i == 2);
458 shd = &pv->slice_data_shd[!is_chroma || ctx->chroma_factor == CFACTOR_Y444];
459 if (i < 3) {
460 slice_data_info.plane = i;
461 slice_data_info.bits_per_sample = desc->comp[i].depth;
462 ff_vk_shader_update_desc_buffer(vkctx, exec, shd, 0, 0, 0,
463 slice_data_buf, 0, slice_data_buf->size,
464 VK_FORMAT_UNDEFINED);
465 ff_vk_shader_update_img_array(vkctx, exec, shd, frame, views, 0, 1,
466 VK_IMAGE_LAYOUT_GENERAL, VK_NULL_HANDLE);
467 ff_vk_exec_bind_shader(vkctx, exec, shd);
468 ff_vk_shader_update_push_const(vkctx, exec, shd, VK_SHADER_STAGE_COMPUTE_BIT,
469 0, sizeof(SliceDataInfo), &slice_data_info);
470 vk->CmdDispatch(exec->buf, ctx->slices_width, ctx->mb_height, 1);
471 } else {
472 ff_vk_shader_update_desc_buffer(vkctx, exec, &pv->alpha_data_shd, 0, 0, 0,
473 slice_data_buf, 0, slice_data_buf->size,
474 VK_FORMAT_UNDEFINED);
475 ff_vk_shader_update_img(vkctx, exec, &pv->alpha_data_shd, 0, 1, 0, views[3],
476 VK_IMAGE_LAYOUT_GENERAL, VK_NULL_HANDLE);
477 ff_vk_exec_bind_shader(vkctx, exec, &pv->alpha_data_shd);
478 vk->CmdDispatch(exec->buf, ctx->mb_width, ctx->mb_height, 1);
479 }
480 }
481
482 /* Wait for writes to slice buffer. */
483 vk->CmdPipelineBarrier2(exec->buf, &(VkDependencyInfo) {
484 .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
485 .pBufferMemoryBarriers = & (VkBufferMemoryBarrier2) {
486 .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER_2,
487 .pNext = NULL,
488 .srcStageMask = VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT,
489 .srcAccessMask = VK_ACCESS_2_SHADER_WRITE_BIT,
490 .dstStageMask = VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT,
491 .dstAccessMask = VK_ACCESS_2_SHADER_READ_BIT,
492 .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
493 .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
494 .buffer = slice_data_buf->buf,
495 .offset = 0,
496 .size = slice_data_buf->size,
497 },
498 .bufferMemoryBarrierCount = 1,
499 });
500
501 /* Estimate slice bits and error for each quant */
502 ff_vk_shader_update_desc_buffer(vkctx, exec, &pv->estimate_slice_shd, 0, 0, 0,
503 slice_data_buf, 0, slice_data_buf->size,
504 VK_FORMAT_UNDEFINED);
505 ff_vk_shader_update_desc_buffer(vkctx, exec, &pv->estimate_slice_shd, 0, 1, 0,
506 slice_score_buf, 0, slice_score_buf->size,
507 VK_FORMAT_UNDEFINED);
508 ff_vk_shader_update_desc_buffer(vkctx, exec, &pv->estimate_slice_shd, 0, 2, 0,
509 &pv->prores_data_tables_buf, 0, pv->prores_data_tables_buf.size,
510 VK_FORMAT_UNDEFINED);
511 ff_vk_exec_bind_shader(vkctx, exec, &pv->estimate_slice_shd);
512 vk->CmdDispatch(exec->buf, (ctx->slices_per_picture + pv->estimate_slices_per_wg - 1) /
513 pv->estimate_slices_per_wg,
514 ctx->force_quant ? 1 : (max_quant - min_quant + 1), 1);
515
516 /* Wait for writes to score buffer. */
517 vk->CmdPipelineBarrier2(exec->buf, &(VkDependencyInfo) {
518 .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
519 .pBufferMemoryBarriers = & (VkBufferMemoryBarrier2) {
520 .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER_2,
521 .pNext = NULL,
522 .srcStageMask = VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT,
523 .srcAccessMask = VK_ACCESS_2_SHADER_WRITE_BIT | VK_ACCESS_2_SHADER_READ_BIT,
524 .dstStageMask = VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT,
525 .dstAccessMask = VK_ACCESS_2_SHADER_WRITE_BIT | VK_ACCESS_2_SHADER_READ_BIT,
526 .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
527 .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
528 .buffer = slice_score_buf->buf,
529 .offset = 0,
530 .size = slice_score_buf->size,
531 },
532 .bufferMemoryBarrierCount = 1,
533 });
534
535 /* Compute optimal quant value for each slice */
536 ff_vk_shader_update_desc_buffer(vkctx, exec, &pv->trellis_node_shd, 0, 0, 0,
537 slice_score_buf, 0, slice_score_buf->size,
538 VK_FORMAT_UNDEFINED);
539 ff_vk_exec_bind_shader(vkctx, exec, &pv->trellis_node_shd);
540 vk->CmdDispatch(exec->buf, 1, 1, 1);
541
542 /* Wait for writes to quant buffer. */
543 vk->CmdPipelineBarrier2(exec->buf, &(VkDependencyInfo) {
544 .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
545 .pBufferMemoryBarriers = & (VkBufferMemoryBarrier2) {
546 .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER_2,
547 .pNext = NULL,
548 .srcStageMask = VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT,
549 .srcAccessMask = VK_ACCESS_2_SHADER_WRITE_BIT,
550 .dstStageMask = VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT,
551 .dstAccessMask = VK_ACCESS_2_SHADER_WRITE_BIT | VK_ACCESS_2_SHADER_READ_BIT,
552 .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
553 .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
554 .buffer = slice_score_buf->buf,
555 .offset = 0,
556 .size = slice_score_buf->size,
557 },
558 .bufferMemoryBarrierCount = 1,
559 });
560
561 /* Encode slices. */
562 encode_info = (EncodeSliceInfo) {
563 .bytestream = pkt_vk_buf->address,
564 .slice_sizes = pd->slice_sizes_ref[picture_idx]->address,
565 .slot_size = pv->slice_slot_size,
566 };
567 ff_vk_shader_update_desc_buffer(vkctx, exec, &pv->encode_slice_shd, 0, 0, 0,
568 slice_data_buf, 0, slice_data_buf->size,
569 VK_FORMAT_UNDEFINED);
570 ff_vk_shader_update_desc_buffer(vkctx, exec, &pv->encode_slice_shd, 0, 1, 0,
571 slice_score_buf, 0, slice_score_buf->size,
572 VK_FORMAT_UNDEFINED);
573 ff_vk_shader_update_desc_buffer(vkctx, exec, &pv->encode_slice_shd, 0, 2, 0,
574 &pv->prores_data_tables_buf, 0, pv->prores_data_tables_buf.size,
575 VK_FORMAT_UNDEFINED);
576 ff_vk_exec_bind_shader(vkctx, exec, &pv->encode_slice_shd);
577 ff_vk_shader_update_push_const(vkctx, exec, &pv->encode_slice_shd,
578 VK_SHADER_STAGE_COMPUTE_BIT, 0, sizeof(encode_info), &encode_info);
579 vk->CmdDispatch(exec->buf, FFALIGN(ctx->slices_per_picture, 64) / 64,
580 ctx->num_planes, 1);
581
582 /* Gather the sparse slots into the contiguous bitstream, in the same
583 * submission. Picture 1 follows the header and seek table after
584 * picture 0's payload, whose size the gather of picture 0 wrote. */
585 RET(ff_vk_seg_gather(vkctx, exec, &pv->gather_shd,
586 pd->slice_sizes_ref[picture_idx], 0, ctx->slices_per_picture,
587 pkt_vk_buf, pv->slice_slot_size, pd->gathered_ref,
588 pv->payload_off + picture_idx * (8 + ctx->slices_per_picture * 2),
589 picture_idx ? pd->slice_sizes_ref[0]->address +
590 ctx->slices_per_picture * sizeof(uint32_t) : 0));
591
592fail:
593 return err;
594}
595
597 uint8_t **orig_buf, int flags,
599 enum AVColorTransferCharacteristic color_trc,
600 enum AVColorSpace colorspace)
601{
602 uint8_t *buf, *tmp;
603 uint8_t frame_flags;
604
605 // frame atom
606 *orig_buf += 4; // frame size
607 bytestream_put_be32 (orig_buf, FRAME_ID); // frame container ID
608 buf = *orig_buf;
609
610 // frame header
611 tmp = buf;
612 buf += 2; // frame header size will be stored here
613 bytestream_put_be16 (&buf, ctx->chroma_factor != CFACTOR_Y422 || ctx->alpha_bits ? 1 : 0);
614 bytestream_put_buffer(&buf, (uint8_t*)ctx->vendor, 4);
615 bytestream_put_be16 (&buf, avctx->width);
616 bytestream_put_be16 (&buf, avctx->height);
617
618 frame_flags = ctx->chroma_factor << 6;
620 frame_flags |= (flags & AV_FRAME_FLAG_TOP_FIELD_FIRST) ? 0x04 : 0x08;
621 bytestream_put_byte (&buf, frame_flags);
622
623 bytestream_put_byte (&buf, 0); // reserved
624 bytestream_put_byte (&buf, color_primaries);
625 bytestream_put_byte (&buf, color_trc);
626 bytestream_put_byte (&buf, colorspace);
627 bytestream_put_byte (&buf, ctx->alpha_bits >> 3);
628 bytestream_put_byte (&buf, 0); // reserved
629 if (ctx->quant_sel != QUANT_MAT_DEFAULT) {
630 bytestream_put_byte (&buf, 0x03); // matrix flags - both matrices are present
631 bytestream_put_buffer(&buf, ctx->quant_mat, 64); // luma quantisation matrix
632 bytestream_put_buffer(&buf, ctx->quant_chroma_mat, 64); // chroma quantisation matrix
633 } else {
634 bytestream_put_byte (&buf, 0x00); // matrix flags - default matrices are used
635 }
636 bytestream_put_be16 (&tmp, buf - *orig_buf); // write back frame header size
637 return buf;
638}
639
640/* Return the assembled-frame buffer to its pool when the packet is freed. */
641static void prores_vk_packet_free(void *opaque, uint8_t *data)
642{
643 av_refstruct_unref(&opaque);
644}
645
647{
648 ProresVulkanContext *pv = avctx->priv_data;
649 ProresContext *ctx = &pv->ctx;
651 FFVulkanContext *vkctx = &pv->vkctx;
652 FFVulkanFunctions *vk = &vkctx->vkfn;
653 FFVkBuffer *wrap_buf = pd->gathered_ref;
654 uint8_t *orig_buf, *buf;
655 uint8_t *picture_size_pos;
656 int picture_idx;
657 int frame_size, picture_size;
658 VkMappedMemoryRange invalidate_data;
659
660 /* Make sure encoding's done */
661 ff_vk_exec_wait(vkctx, exec);
662
663 /* Invalidate the gathered bitstream if needed */
664 invalidate_data = (VkMappedMemoryRange) {
665 .sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,
666 .offset = 0,
667 .size = VK_WHOLE_SIZE,
668 };
669 if (!(wrap_buf->flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)) {
670 invalidate_data.memory = wrap_buf->mem;
671 vk->InvalidateMappedMemoryRanges(vkctx->hwctx->act_dev, 1, &invalidate_data);
672 }
673
674 /* Write frame atom */
675 orig_buf = wrap_buf->mapped_mem;
676 buf = write_frame_header(avctx, ctx, &orig_buf, pd->flags,
677 pd->color_primaries, pd->color_trc,
678 pd->colorspace);
679
680 for (picture_idx = 0; picture_idx < ctx->pictures_per_frame; picture_idx++) {
681 FFVkBuffer *slice_sizes_buf = pd->slice_sizes_ref[picture_idx];
682 const uint32_t *sizes;
683
684 /* Invalidate slice sizes if needed */
685 if (!(slice_sizes_buf->flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)) {
686 invalidate_data.memory = slice_sizes_buf->mem;
687 vk->InvalidateMappedMemoryRanges(vkctx->hwctx->act_dev, 1, &invalidate_data);
688 }
689
690 /* Write picture header */
691 picture_size_pos = buf + 1;
692 bytestream_put_byte(&buf, 0x40); // picture header size (in bits)
693 buf += 4; // picture data size will be stored here
694 bytestream_put_be16(&buf, ctx->slices_per_picture);
695 bytestream_put_byte(&buf, av_log2(ctx->mbs_per_slice) << 4); // slice width and height in MBs
696
697 /* Write the seek table from the per-slice sizes; the payload itself
698 * was already packed to match by the gather pass. */
699 sizes = (const uint32_t *)slice_sizes_buf->mapped_mem;
700 for (int i = 0; i < ctx->slices_per_picture; i++)
701 bytestream_put_be16(&buf, sizes[i]);
702 av_assert1(picture_idx || buf - wrap_buf->mapped_mem == pv->payload_off);
703
704 /* Calculate final size */
705 buf += sizes[ctx->slices_per_picture];
706
707 /* Write picture size with header */
708 picture_size = buf - (picture_size_pos - 1);
709 bytestream_put_be32(&picture_size_pos, picture_size);
710
711 /* Slice output buffers no longer needed */
712 av_refstruct_unref(&pd->out_data_ref[picture_idx]);
713 av_refstruct_unref(&pd->slice_sizes_ref[picture_idx]);
714 av_refstruct_unref(&pd->slice_data_ref[picture_idx]);
715 av_refstruct_unref(&pd->slice_score_ref[picture_idx]);
716 }
717
718 /* Write frame size in header */
719 orig_buf -= 8;
720 frame_size = buf - orig_buf;
721 bytestream_put_be32(&orig_buf, frame_size);
722
723 memset(buf, 0, AV_INPUT_BUFFER_PADDING_SIZE);
724
725 /* Hand the buffer to the packet with no copy: pkt->buf references the
726 * pooled Vulkan buffer, returned to its pool when the packet is freed. */
727 pkt->buf = av_buffer_create(wrap_buf->mapped_mem, wrap_buf->size,
729 if (!pkt->buf) {
731 return AVERROR(ENOMEM);
732 }
733 pd->gathered_ref = NULL; /* ownership passed to pkt->buf */
734 pkt->data = wrap_buf->mapped_mem;
735 pkt->size = frame_size;
736
737 av_log(avctx, AV_LOG_VERBOSE, "Encoded data: %iMiB\n", pkt->size / (1024*1024));
738
739 return 0;
740}
741
743 AVFrame *frame)
744{
745 int err;
746 ProresVulkanContext *pv = avctx->priv_data;
748
749 pd->color_primaries = frame->color_primaries;
750 pd->color_trc = frame->color_trc;
751 pd->colorspace = frame->colorspace;
752 pd->flags = frame->flags;
753
754 err = ff_vk_exec_start(&pv->vkctx, exec);
755 if (err < 0)
756 return err;
757
758 for (int i = 0; i < pv->ctx.pictures_per_frame; i++) {
759 err = encode_picture(avctx, exec, frame, i);
760 if (err < 0) {
761 ff_vk_exec_discard(&pv->vkctx, exec);
762 return err;
763 }
764 }
765
766 return ff_vk_exec_submit(&pv->vkctx, exec);
767}
768
774
776{
777 ProresVulkanContext *pv = avctx->priv_data;
778 ff_vk_encode_loop_flush(avctx, &pv->loop);
779}
780
782{
783 ProresVulkanContext *pv = avctx->priv_data;
784 ProresContext *ctx = &pv->ctx;
785 FFVulkanContext *vkctx = &pv->vkctx;
786
787 ff_vk_exec_pool_free(vkctx, &pv->e);
788
789 if (ctx->alpha_bits)
791
792 ff_vk_shader_free(vkctx, &pv->slice_data_shd[0]);
793 ff_vk_shader_free(vkctx, &pv->slice_data_shd[1]);
797 ff_vk_shader_free(vkctx, &pv->gather_shd);
798
800
801 if (pv->exec_ctx_info) {
802 for (int i = 0; i < pv->async_depth; i++) {
804 for (int j = 0; j < 2; j++) {
809 }
811 }
813 }
815
821
822 ff_vk_uninit(vkctx);
823
824 return 0;
825}
826
828{
829 ProresVulkanContext *pv = avctx->priv_data;
830 ProresContext *ctx = &pv->ctx;
831 int err = 0, i, q;
832 FFVulkanContext *vkctx = &pv->vkctx;
833
834 /* Init vulkan */
835 RET(ff_vk_init(vkctx, avctx, NULL, avctx->hw_frames_ctx));
836
837 pv->qf = ff_vk_qf_find(vkctx, VK_QUEUE_COMPUTE_BIT, 0);
838 if (!pv->qf) {
839 av_log(avctx, AV_LOG_ERROR, "Device has no compute queues!\n");
840 return AVERROR(ENOTSUP);
841 }
842
843 RET(ff_vk_exec_pool_init(vkctx, pv->qf, &pv->e, pv->async_depth, 0, 0, 0, NULL));
844
845 /* Init common prores structures */
846 err = ff_prores_kostya_encode_init(avctx, ctx, vkctx->frames->sw_format);
847 if (err < 0)
848 return err;
849
850 /* Async data pool */
851 pv->async_depth = pv->e.pool_size;
852 pv->exec_ctx_info = av_calloc(pv->async_depth, sizeof(*pv->exec_ctx_info));
853 if (!pv->exec_ctx_info)
854 return AVERROR(ENOMEM);
855 for (int i = 0; i < pv->async_depth; i++)
856 pv->e.contexts[i].opaque = &pv->exec_ctx_info[i];
857
858 RET(ff_vk_encode_loop_init(vkctx, &pv->e, &pv->loop,
860
861 /* Compile shaders used by encoder */
867 RET(ff_vk_seg_gather_init(vkctx, &pv->e, &pv->gather_shd));
868
869 /* Size slots for the entropy coder's worst case; bits_per_mb is only a rate-control average */
870 {
871 size_t samples = ctx->mbs_per_slice *
872 (256 + (ctx->chroma_factor == CFACTOR_Y444 ? 512 : 256));
873 pv->slice_slot_size = 2 + 2 * ctx->num_planes + samples * 8;
874 if (ctx->alpha_bits)
875 pv->slice_slot_size += (ctx->mbs_per_slice * 256 *
876 (1 + ctx->alpha_bits + 1) + 7) >> 3;
878 UINT16_MAX + 2 + 2 * ctx->num_planes);
880 }
881
882 /* First picture's payload offset: everything before it in the stream has
883 * a static size, so the gather pass writes the payload directly in place */
884 {
885 uint8_t tmp[256];
886 uint8_t *start = tmp;
887 uint8_t *end = write_frame_header(avctx, ctx, &start, 0, 0, 0, 0);
888 pv->payload_off = (end - tmp) + 8 + ctx->slices_per_picture * 2;
889 }
890
891 if (ctx->alpha_bits)
893
894 /* Create prores data tables uniform buffer. */
896 sizeof(ProresDataTables), NULL, NULL,
897 VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT |
898 VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT,
899 VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT |
900 VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT));
901 RET(ff_vk_map_buffer(vkctx, &pv->prores_data_tables_buf, (void *)&pv->tables, 0));
902 for (q = 0; q < 128; ++q) {
903 for (i = 0; i < 64; i++) {
904 pv->tables->qmat[q][i] = ctx->quant_mat[ctx->scantable[i]] * q;
905 pv->tables->qmat_chroma[q][i] = ctx->quant_chroma_mat[ctx->scantable[i]] * q;
906 }
907 }
908
909fail:
910 return err;
911}
912
913#define OFFSET(x) offsetof(ProresVulkanContext, x)
914#define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM
915
916static const AVOption options[] = {
917 { "mbs_per_slice", "macroblocks per slice", OFFSET(ctx.mbs_per_slice),
918 AV_OPT_TYPE_INT, { .i64 = 8 }, 1, MAX_MBS_PER_SLICE, VE },
919 { "profile", NULL, OFFSET(ctx.profile), AV_OPT_TYPE_INT,
920 { .i64 = PRORES_PROFILE_AUTO },
921 PRORES_PROFILE_AUTO, PRORES_PROFILE_4444XQ, VE, .unit = "profile" },
922 { "auto", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = PRORES_PROFILE_AUTO },
923 0, 0, VE, .unit = "profile" },
924 { "proxy", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = PRORES_PROFILE_PROXY },
925 0, 0, VE, .unit = "profile" },
926 { "lt", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = PRORES_PROFILE_LT },
927 0, 0, VE, .unit = "profile" },
928 { "standard", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = PRORES_PROFILE_STANDARD },
929 0, 0, VE, .unit = "profile" },
930 { "hq", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = PRORES_PROFILE_HQ },
931 0, 0, VE, .unit = "profile" },
932 { "4444", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = PRORES_PROFILE_4444 },
933 0, 0, VE, .unit = "profile" },
934 { "4444xq", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = PRORES_PROFILE_4444XQ },
935 0, 0, VE, .unit = "profile" },
936 { "vendor", "vendor ID", OFFSET(ctx.vendor),
937 AV_OPT_TYPE_STRING, { .str = "Lavc" }, 0, 0, VE },
938 { "bits_per_mb", "desired bits per macroblock", OFFSET(ctx.bits_per_mb),
939 AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 8192, VE },
940 { "quant_mat", "quantiser matrix", OFFSET(ctx.quant_sel), AV_OPT_TYPE_INT,
941 { .i64 = -1 }, -1, QUANT_MAT_DEFAULT, VE, .unit = "quant_mat" },
942 { "auto", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = -1 },
943 0, 0, VE, .unit = "quant_mat" },
944 { "proxy", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = QUANT_MAT_PROXY },
945 0, 0, VE, .unit = "quant_mat" },
946 { "lt", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = QUANT_MAT_LT },
947 0, 0, VE, .unit = "quant_mat" },
948 { "standard", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = QUANT_MAT_STANDARD },
949 0, 0, VE, .unit = "quant_mat" },
950 { "hq", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = QUANT_MAT_HQ },
951 0, 0, VE, .unit = "quant_mat" },
952 { "default", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = QUANT_MAT_DEFAULT },
953 0, 0, VE, .unit = "quant_mat" },
954 { "alpha_bits", "bits for alpha plane", OFFSET(ctx.alpha_bits), AV_OPT_TYPE_INT,
955 { .i64 = 16 }, 0, 16, VE },
956 { "async_depth", "Internal parallelization depth", OFFSET(async_depth), AV_OPT_TYPE_INT,
957 { .i64 = 2 }, 1, INT_MAX, VE },
958 { NULL }
959};
960
961static const AVClass proresenc_class = {
962 .class_name = "ProRes vulkan encoder",
963 .item_name = av_default_item_name,
964 .option = options,
965 .version = LIBAVUTIL_VERSION_INT,
966};
967
969 HW_CONFIG_ENCODER_FRAMES(VULKAN, VULKAN),
971 NULL,
972};
973
975 .p.name = "prores_ks_vulkan",
976 CODEC_LONG_NAME("Apple ProRes (iCodec Pro)"),
977 .p.type = AVMEDIA_TYPE_VIDEO,
978 .p.id = AV_CODEC_ID_PRORES,
979 .priv_data_size = sizeof(ProresVulkanContext),
980 .init = encode_init,
984 .p.capabilities = AV_CODEC_CAP_DELAY |
989 .hw_configs = prores_ks_hw_configs,
990 .color_ranges = AVCOL_RANGE_MPEG,
991 .p.priv_class = &proresenc_class,
993 .caps_internal = FF_CODEC_CAP_INIT_CLEANUP,
994};
const FFCodec ff_prores_ks_vulkan_encoder
#define VE
Definition amfenc_av1.c:30
static AVFormatContext * ctx
static av_cold void close(AVCodecParserContext *s)
Definition apv_parser.c:197
static av_cold int encode_init(AVCodecContext *avctx)
Definition asvenc.c:373
simple assert() macros that are a bit more flexible than ISO C assert().
#define av_assert1(cond)
assert() equivalent, that does not lie in speed critical code.
Definition avassert.h:58
Libavcodec external API header.
refcounted data buffer API
static av_always_inline void bytestream_put_buffer(uint8_t **b, const uint8_t *src, unsigned int size)
Definition bytestream.h:372
#define flags(name, subs,...)
Definition cbs_h264.c:74
#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 const AVColorPrimariesDesc color_primaries[AVCOL_PRI_NB]
Definition csp.c:76
static av_cold int encode_close(AVCodecContext *avctx)
Definition dcaenc.c:354
static AVPacket * pkt
static AVFrame * frame
int(* init)(AVBSFContext *ctx)
Definition dts2pts.c:608
#define FF_INPUT_BUFFER_MIN_SIZE
Used by some encoders as upper bound for the length of headers.
Definition encode.h:34
#define MAX_PLANES
Definition ffv1.h:44
static int get_packet(AVCodecContext *avctx, FFVkExecContext *exec, AVPacket *pkt)
#define AV_NUM_DATA_POINTERS
Definition frame.h:473
static const uint8_t frame_size[4]
Definition g723_1.h:222
#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
@ AV_OPT_TYPE_STRING
Underlying C type is a uint8_t* that is either NULL or points to a C string allocated with the av_mal...
Definition opt.h:275
#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_FLAG_INTERLACED_DCT
Use interlaced DCT.
Definition avcodec.h:310
#define AV_CODEC_CAP_HARDWARE
Codec is backed by a hardware implementation.
Definition codec.h:133
@ AV_CODEC_ID_PRORES
Definition codec_id.h:198
#define AV_INPUT_BUFFER_PADDING_SIZE
Required number of additionally allocated bytes at the end of the input bitstream for decoding.
Definition defs.h:40
AVBufferRef * av_buffer_create(uint8_t *data, size_t size, void(*free)(void *opaque, uint8_t *data), void *opaque, int flags)
Create an AVBuffer from an existing array.
Definition buffer.c:55
#define AVERROR(e)
Definition error.h:45
#define AV_FRAME_FLAG_TOP_FIELD_FIRST
A flag to mark frames where the top field is displayed first if the content is interlaced.
Definition frame.h:700
#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_DEVICE(format, device_type_)
Definition hwconfig.h:97
#define HW_CONFIG_ENCODER_FRAMES(format, device_type_)
Definition hwconfig.h:100
API-specific header for AV_HWDEVICE_TYPE_VULKAN.
static const int sizes[][2]
Definition img2dec.c:62
#define av_log2
Definition intmath.h:84
#define DCTSIZE
Definition jfdctfst.c:73
#define av_cold
Definition attributes.h:117
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification.
Definition internal.h:97
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_create_buf(FFVulkanContext *s, FFVkBuffer *buf, size_t size, void *pNext, void *alloc_pNext, VkBufferUsageFlags usage, VkMemoryPropertyFlagBits flags)
Definition vulkan.c:1204
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
int ff_vk_shader_update_img(FFVulkanContext *s, FFVkExecContext *e, FFVulkanShader *shd, int set, int bind, int offs, VkImageView view, VkImageLayout layout, VkSampler sampler)
Sets an image descriptor for specified shader and binding.
Definition vulkan.c:2665
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_free_buf(FFVulkanContext *s, FFVkBuffer *buf)
Definition vulkan.c:1418
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
Utility Preprocessor macros.
#define FFMIN(a, b)
Definition macros.h:49
#define FFALIGN(x, a)
Definition macros.h:78
void * av_calloc(size_t nmemb, size_t size)
Definition mem.c:264
Memory handling functions.
const char data[16]
Definition mxf.c:149
AVOptions.
int av_pix_fmt_count_planes(enum AVPixelFormat pix_fmt)
Definition pixdesc.c:3500
const AVPixFmtDescriptor * av_pix_fmt_desc_get(enum AVPixelFormat pix_fmt)
Definition pixdesc.c:3460
@ AVCOL_RANGE_MPEG
Narrow or limited range content.
Definition pixfmt.h:766
@ AV_PIX_FMT_VULKAN
Vulkan hardware images.
Definition pixfmt.h:379
AVColorPrimaries
Chromaticity coordinates of the source primaries.
Definition pixfmt.h:642
AVColorTransferCharacteristic
Color Transfer Characteristic.
Definition pixfmt.h:672
AVColorSpace
YUV colorspace type.
Definition pixfmt.h:706
const AVProfile ff_prores_profiles[]
Definition profiles.c:175
#define FRAME_ID
Definition proresdata.h:28
static const AVClass proresenc_class
av_cold int ff_prores_kostya_encode_init(AVCodecContext *avctx, ProresContext *ctx, enum AVPixelFormat pix_fmt)
@ QUANT_MAT_STANDARD
@ QUANT_MAT_DEFAULT
#define CFACTOR_Y444
#define CFACTOR_Y422
@ PRORES_PROFILE_4444
@ PRORES_PROFILE_STANDARD
@ PRORES_PROFILE_LT
@ PRORES_PROFILE_4444XQ
@ PRORES_PROFILE_AUTO
@ PRORES_PROFILE_HQ
@ PRORES_PROFILE_PROXY
#define MAX_MBS_PER_SLICE
#define MAX_STORED_Q
const unsigned int ff_prores_ks_alpha_data_comp_spv_len
const unsigned char ff_prores_ks_alpha_data_comp_spv_data[]
static int init_estimate_slice_pipeline(ProresVulkanContext *pv, FFVulkanShader *shd)
static int get_packet(AVCodecContext *avctx, FFVkExecContext *exec, AVPacket *pkt)
const unsigned int ff_prores_ks_slice_data_comp_spv_len
const unsigned int ff_prores_ks_encode_slice_comp_spv_len
static int encode_picture(AVCodecContext *avctx, FFVkExecContext *exec, AVFrame *frame, int picture_idx)
static av_cold int encode_init(AVCodecContext *avctx)
static av_cold int encode_close(AVCodecContext *avctx)
const unsigned int ff_prores_ks_trellis_node_comp_spv_len
static int init_alpha_data_pipeline(ProresVulkanContext *pv, FFVulkanShader *shd)
static const AVCodecHWConfigInternal *const prores_ks_hw_configs[]
static int vulkan_encode_prores_receive_packet(AVCodecContext *avctx, AVPacket *pkt)
static int init_trellis_node_pipeline(ProresVulkanContext *pv, FFVulkanShader *shd)
static void prores_vk_packet_free(void *opaque, uint8_t *data)
static av_cold void vulkan_encode_prores_flush(AVCodecContext *avctx)
static int vulkan_encode_prores_submit_frame(AVCodecContext *avctx, FFVkExecContext *exec, AVFrame *frame)
static int init_slice_data_pipeline(ProresVulkanContext *pv, FFVulkanShader *shd, int blocks_per_mb)
#define OFFSET(x)
const unsigned char ff_prores_ks_trellis_node_comp_spv_data[]
static uint8_t * write_frame_header(AVCodecContext *avctx, ProresContext *ctx, uint8_t **orig_buf, int flags, enum AVColorPrimaries color_primaries, enum AVColorTransferCharacteristic color_trc, enum AVColorSpace colorspace)
const unsigned int ff_prores_ks_estimate_slice_comp_spv_len
static int init_encode_slice_pipeline(ProresVulkanContext *pv, FFVulkanShader *shd)
const unsigned char ff_prores_ks_estimate_slice_comp_spv_data[]
const unsigned char ff_prores_ks_slice_data_comp_spv_data[]
const unsigned char ff_prores_ks_encode_slice_comp_spv_data[]
bitstream writer API
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:120
static void av_refstruct_pool_uninit(AVRefStructPool **poolp)
Mark the pool as being available for freeing.
Definition refstruct.h:292
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
int flags
AV_CODEC_FLAG_*.
Definition avcodec.h:500
void * priv_data
Definition avcodec.h:470
This structure describes decoded (raw) audio or video data.
Definition frame.h:472
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:183
VkDevice act_dev
Active device.
VkDeviceAddress slice_sizes
VkDeviceAddress bytestream
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
AVHWFramesContext * frames
Definition vulkan.h:344
AVVulkanDeviceContext * hwctx
Definition vulkan.h:340
VkMemoryPropertyFlagBits host_cached_flag
Definition vulkan.h:336
VkPhysicalDeviceSubgroupSizeControlProperties subgroup_props
Definition vulkan.h:304
FFVulkanFunctions vkfn
Definition vulkan.h:296
unsigned mb_height
height of the current picture in mb
Definition proresdec.h:54
const struct prores_profile * profile_info
unsigned mb_width
width of the current picture in mb
Definition proresdec.h:53
int16_t qmat_chroma[128][64]
AVRefStructPool * slice_data_buf_pool
AVRefStructPool * gathered_buf_pool
AVRefStructPool * slice_sizes_buf_pool
AVVulkanDeviceQueueFamily * qf
VulkanEncodeProresFrameData * exec_ctx_info
FFVulkanShader slice_data_shd[2]
AVRefStructPool * slice_score_buf_pool
int16_t rows[MAX_PLANES *MAX_MBS_PER_SLICE *256]
int error[MAX_STORED_Q][4]
int total_bits[MAX_STORED_Q]
int total_error[MAX_STORED_Q]
int bits[MAX_STORED_Q][4]
enum AVColorPrimaries color_primaries
enum AVColorTransferCharacteristic color_trc
#define av_freep(p)
#define av_log(a,...)
static uint8_t tmp[40]
Definition aes_ctr.c:52
#define NONE
Definition vf_drawvg.c:262
@ 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
static int ff_vk_map_buffer(FFVulkanContext *s, FFVkBuffer *buf, uint8_t **mem, int invalidate)
Definition vulkan.h:646
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 ...