FFmpeg
Loading...
Searching...
No Matches
vulkan_dpx.c
Go to the documentation of this file.
1/*
2 * Copyright (c) 2025 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
22#include "vulkan_decode.h"
23#include "hwaccel_internal.h"
24
25#include "dpx.h"
26#include "libavutil/mem.h"
27
28extern const unsigned char ff_dpx_unpack_comp_spv_data[];
29extern const unsigned int ff_dpx_unpack_comp_spv_len;
30
31extern const unsigned char ff_dpx_copy_comp_spv_data[];
32extern const unsigned int ff_dpx_copy_comp_spv_len;
33
35 .codec_id = AV_CODEC_ID_DPX,
36 .queue_flags = VK_QUEUE_COMPUTE_BIT,
37};
38
42
47
48typedef struct DecodePushData {
52 int stride;
55 int shift;
57
59 const AVBufferRef *buffer_ref,
60 const uint8_t *buffer,
61 uint32_t size)
62{
65 DPXDecContext *dpx = avctx->priv_data;
66
68 FFVulkanDecodePicture *vp = &pp->vp;
69
70 /* Host map the frame data if supported */
71 if (!vp->slices_buf &&
72 ctx->s.extensions & FF_VK_EXT_EXTERNAL_HOST_MEMORY)
73 ff_vk_host_map_buffer(&ctx->s, &vp->slices_buf, (uint8_t *)buffer,
74 size, buffer_ref,
75 VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
76
77 return 0;
78}
79
81 const uint8_t *data,
82 uint32_t size)
83{
84 DPXDecContext *dpx = avctx->priv_data;
85
87 FFVulkanDecodePicture *vp = &pp->vp;
88
89 if (!vp->slices_buf) {
90 int err = ff_vk_decode_add_slice(avctx, vp, data, size, 0,
91 NULL, NULL);
92 if (err < 0)
93 return err;
94 }
95
96 return 0;
97}
98
100{
101 int err;
104 FFVulkanFunctions *vk = &ctx->s.vkfn;
105
106 DPXDecContext *dpx = avctx->priv_data;
107 DPXVulkanDecodeContext *dxv = ctx->sd_ctx;
108
110 FFVulkanDecodePicture *vp = &pp->vp;
111
112 int unpack = (avctx->bits_per_raw_sample == 12 && !dpx->packing) ||
113 avctx->bits_per_raw_sample == 10;
114
115 FFVkBuffer *slices_buf = vp->slices_buf;
116
117 VkImageMemoryBarrier2 img_bar[8];
118 int nb_img_bar = 0;
119
120 FFVkExecContext *exec = ff_vk_exec_get(&ctx->s, &ctx->exec_pool);
121 err = ff_vk_exec_start(&ctx->s, exec);
122 if (err < 0)
123 return err;
124
125 /* Prepare deps */
126 RET(ff_vk_exec_add_dep_frame(&ctx->s, exec, dpx->frame,
127 VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
128 VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT));
129
130 /* Exec-owned output views: freed on exec recycle, so releasing a picture
131 * needs no blocking wait. No mirror_sem: nothing consumes vp->sem here. */
132 VkImageView views[AV_NUM_DATA_POINTERS];
133 RET(ff_vk_create_imageviews(&ctx->s, exec, views, dpx->frame,
135
137
138 AVVkFrame *vkf = (AVVkFrame *)dpx->frame->data[0];
139 for (int i = 0; i < 4; i++) {
140 vkf->layout[i] = VK_IMAGE_LAYOUT_UNDEFINED;
141 vkf->access[i] = VK_ACCESS_2_NONE;
142 }
143
144 ff_vk_frame_barrier(&ctx->s, exec, dpx->frame, img_bar, &nb_img_bar,
145 VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
146 VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT,
147 VK_ACCESS_2_SHADER_STORAGE_WRITE_BIT,
148 VK_IMAGE_LAYOUT_GENERAL,
149 VK_QUEUE_FAMILY_IGNORED);
150
151 vk->CmdPipelineBarrier2(exec->buf, &(VkDependencyInfo) {
152 .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
153 .pImageMemoryBarriers = img_bar,
154 .imageMemoryBarrierCount = nb_img_bar,
155 });
156 nb_img_bar = 0;
157
158 FFVulkanShader *shd = &dxv->shader;
159 ff_vk_shader_update_img_array(&ctx->s, exec, shd,
160 dpx->frame, views,
161 0, 0,
162 VK_IMAGE_LAYOUT_GENERAL,
163 VK_NULL_HANDLE);
165 0, 1, 0,
166 slices_buf,
167 0, slices_buf->size,
168 VK_FORMAT_UNDEFINED);
169 if (!unpack) {
171 0, 2, 0,
172 slices_buf,
173 0, slices_buf->size,
174 VK_FORMAT_UNDEFINED);
176 0, 3, 0,
177 slices_buf,
178 0, slices_buf->size,
179 VK_FORMAT_UNDEFINED);
180 }
181
182 ff_vk_exec_bind_shader(&ctx->s, exec, shd);
183
184 /* Update push data */
186 .bits_per_comp = avctx->bits_per_raw_sample,
187 .nb_comp = dpx->components,
188 .nb_images = ff_vk_count_images(vkf),
189 .stride = dpx->stride,
190 .need_align = dpx->need_align,
191 .padded_10bit = !dpx->unpadded_10bit,
192 .shift = FFALIGN(avctx->bits_per_raw_sample, 8) -
193 avctx->bits_per_raw_sample,
194 };
195
196 ff_vk_shader_update_push_const(&ctx->s, exec, shd,
197 VK_SHADER_STAGE_COMPUTE_BIT,
198 0, sizeof(pd), &pd);
199
200 vk->CmdDispatch(exec->buf,
201 FFALIGN(dpx->frame->width, shd->lg_size[0])/shd->lg_size[0],
202 FFALIGN(dpx->frame->height, shd->lg_size[1])/shd->lg_size[1],
203 1);
204
205 err = ff_vk_exec_submit(&ctx->s, exec);
206 if (err < 0)
207 return err;
208
209 return 0;
210
211fail:
212 ff_vk_exec_discard(&ctx->s, exec);
213 return 0;
214}
215
217 FFVkExecPool *pool, FFVulkanShader *shd, int bits)
218{
219 int err;
220 DPXDecContext *dpx = avctx->priv_data;
221 AVHWFramesContext *dec_frames_ctx;
222 dec_frames_ctx = (AVHWFramesContext *)avctx->hw_frames_ctx->data;
223
224 int unpack = (avctx->bits_per_raw_sample == 12 && !dpx->packing) ||
225 avctx->bits_per_raw_sample == 10;
226
227 SPEC_LIST_CREATE(sl, 2, 2*sizeof(uint32_t))
228 SPEC_LIST_ADD(sl, 0, 32, dpx->endian && bits > 8); /* big endian */
229 if (unpack)
230 SPEC_LIST_ADD(sl, 1, 32, bits == 10); /* packed_10bit */
231 else
232 SPEC_LIST_ADD(sl, 1, 32, FFALIGN(bits, 8)); /* type_bits */
233
234 ff_vk_shader_load(shd, VK_SHADER_STAGE_COMPUTE_BIT, sl,
235 (uint32_t []) { 512, 1, 1 }, 0);
236
238 VK_SHADER_STAGE_COMPUTE_BIT);
239
240 const FFVulkanDescriptorSetBinding desc_set[] = {
241 { /* dst */
242 .type = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
243 .stages = VK_SHADER_STAGE_COMPUTE_BIT,
244 .elems = av_pix_fmt_count_planes(dec_frames_ctx->sw_format),
245 },
246 { /* data_buf */
247 .type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
248 .stages = VK_SHADER_STAGE_COMPUTE_BIT,
249 },
250 { /* data_buf16 */
251 .type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
252 .stages = VK_SHADER_STAGE_COMPUTE_BIT,
253 },
254 { /* data_buf32 */
255 .type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
256 .stages = VK_SHADER_STAGE_COMPUTE_BIT,
257 },
258 };
259 ff_vk_shader_add_descriptor_set(s, shd, desc_set, 2 + (2*!unpack), 0);
260
261 const unsigned char *src = ff_dpx_copy_comp_spv_data;
262 size_t src_len = ff_dpx_copy_comp_spv_len;
263 if (unpack) {
266 }
267 RET(ff_vk_shader_link(s, shd, src, src_len, "main"));
268
269 RET(ff_vk_shader_register_exec(s, pool, shd));
270
271fail:
272 return err;
273}
274
276{
277 DPXVulkanDecodeContext *fv = ctx->sd_ctx;
278
279 ff_vk_shader_free(&ctx->s, &fv->shader);
280
282
283 av_freep(&fv);
284}
285
287{
288 int err;
289 DPXDecContext *dpx = avctx->priv_data;
291
292 switch (dpx->pix_fmt) {
298 return AVERROR(ENOTSUP);
300 if (dpx->unpadded_10bit)
301 return AVERROR(ENOTSUP);
303 default:
304 break;
305 }
306
307 err = ff_vk_decode_init(avctx);
308 if (err < 0)
309 return err;
310
312 DPXVulkanDecodeContext *dxv = ctx->sd_ctx = av_mallocz(sizeof(*dxv));
313 if (!dxv)
314 return AVERROR(ENOMEM);
315
316 ctx->sd_ctx_free = &vk_decode_dpx_uninit;
317
318 RET(init_shader(avctx, &ctx->s, &ctx->exec_pool,
319 &dxv->shader, avctx->bits_per_raw_sample));
320
321fail:
322 return err;
323}
324
326{
327 AVHWDeviceContext *dev_ctx = _hwctx.nc;
328
330 FFVulkanDecodePicture *vp = &pp->vp;
331
332 ff_vk_decode_free_frame(dev_ctx, vp);
333}
334
336 .p.name = "dpx_vulkan",
337 .p.type = AVMEDIA_TYPE_VIDEO,
338 .p.id = AV_CODEC_ID_DPX,
339 .p.pix_fmt = AV_PIX_FMT_VULKAN,
340 .start_frame = &vk_dpx_start_frame,
341 .decode_slice = &vk_dpx_decode_slice,
342 .end_frame = &vk_dpx_end_frame,
343 .free_frame_priv = &vk_dpx_free_frame_priv,
344 .frame_priv_data_size = sizeof(DPXVulkanDecodePicture),
346 .update_thread_context = &ff_vk_update_thread_context,
348 .frame_params = &ff_vk_frame_params,
349 .priv_data_size = sizeof(FFVulkanDecodeContext),
351};
static AVFormatContext * ctx
#define i(width, name, range_min, range_max)
Definition cbs_h264.c:63
#define s(width, name)
Definition cbs_vp9.c:198
#define NULL
Definition coverity.c:32
int(* init)(AVBSFContext *ctx)
Definition dts2pts.c:608
static int unpack(const uint8_t *src, const uint8_t *src_end, uint8_t *dst, int width, int height)
Unpack buffer.
Definition eatgv.c:73
static const uint8_t bits[8]
Definition fastaudio.c:100
#define AV_NUM_DATA_POINTERS
Definition frame.h:473
#define fail
Definition test.h:479
@ AV_CODEC_ID_DPX
Definition codec_id.h:178
#define AVERROR(e)
Definition error.h:45
@ AVMEDIA_TYPE_VIDEO
Definition avutil.h:200
#define HWACCEL_CAP_ASYNC_SAFE
Header providing the internals of AVHWAccel.
#define HWACCEL_CAP_THREAD_SAFE
const struct FFHWAccel ff_dpx_vulkan_hwaccel
Definition vulkan_dpx.c:335
static av_cold void uninit(AVBitStreamFilterContext *ctx)
Macro definitions for various function/variable attributes.
#define av_fallthrough
Definition attributes.h:67
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:2719
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:2240
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:2550
int ff_vk_shader_add_push_const(FFVulkanShader *shd, int offset, int size, VkShaderStageFlagBits stage)
Add/update push constants for execution.
Definition vulkan.c:1613
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:2197
int ff_vk_exec_start(FFVulkanContext *s, FFVkExecContext *e)
Start/submit/wait an execution.
Definition vulkan.c:660
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:2128
void ff_vk_shader_free(FFVulkanContext *s, FFVulkanShader *shd)
Free a shader.
Definition vulkan.c:2791
int ff_vk_shader_register_exec(FFVulkanContext *s, FFVkExecPool *pool, FFVulkanShader *shd)
Register a shader with an exec pool.
Definition vulkan.c:2584
FFVkExecContext * ff_vk_exec_get(FFVulkanContext *s, FFVkExecPool *pool)
Retrieve an execution pool.
Definition vulkan.c:622
int ff_vk_exec_submit(FFVulkanContext *s, FFVkExecContext *e)
Definition vulkan.c:969
void ff_vk_exec_bind_shader(FFVulkanContext *s, FFVkExecContext *e, const FFVulkanShader *shd)
Bind a shader.
Definition vulkan.c:2768
void ff_vk_exec_move_dep_refstruct(FFVulkanContext *s, FFVkExecContext *e, void *obj)
Definition vulkan.c:786
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:2732
int ff_vk_host_map_buffer(FFVulkanContext *s, FFVkBuffer **dst, uint8_t *src_data, VkDeviceSize size, const AVBufferRef *src_buf, VkBufferUsageFlags usage)
Maps a system RAM buffer into a Vulkan buffer.
Definition vulkan.c:1522
void ff_vk_exec_discard(FFVulkanContext *s, FFVkExecContext *e)
Definition vulkan.c:763
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:2444
int ff_vk_exec_add_dep_frame(FFVulkanContext *s, FFVkExecContext *e, AVFrame *f, VkPipelineStageFlagBits2 wait_stage, VkPipelineStageFlagBits2 signal_stage)
Definition vulkan.c:867
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:2758
#define FFALIGN(x, a)
Definition macros.h:78
Memory handling functions.
const char data[16]
Definition mxf.c:149
int av_pix_fmt_count_planes(enum AVPixelFormat pix_fmt)
Definition pixdesc.c:3500
#define AV_PIX_FMT_GBRP10
Definition pixfmt.h:564
@ AV_PIX_FMT_VULKAN
Vulkan hardware images.
Definition pixfmt.h:379
@ AV_PIX_FMT_UYVY422
packed YUV 4:2:2, 16bpp, Cb Y0 Cr Y1
Definition pixfmt.h:88
@ AV_PIX_FMT_YUV444P
planar YUV 4:4:4, 24bpp, (1 Cr & Cb sample per 1x1 Y samples)
Definition pixfmt.h:78
@ AV_PIX_FMT_YUVA444P
planar YUV 4:4:4 32bpp, (1 Cr & Cb sample per 1x1 Y & A samples)
Definition pixfmt.h:174
#define AV_PIX_FMT_GRAY10
Definition pixfmt.h:525
#define AV_PIX_FMT_GBRAP10
Definition pixfmt.h:568
static void av_refstruct_pool_uninit(AVRefStructPool **poolp)
Mark the pool as being available for freeing.
Definition refstruct.h:292
A reference to a data buffer.
Definition buffer.h:82
uint8_t * data
The data buffer.
Definition buffer.h:90
main external API structure.
Definition avcodec.h:443
AVBufferRef * hw_frames_ctx
A reference to the AVHWFramesContext describing the input (for encoding) or output (decoding) frames.
Definition avcodec.h:1471
int bits_per_raw_sample
Bits per sample/pixel of internal libavcodec pixel/sample format.
Definition avcodec.h:1571
struct AVCodecInternal * internal
Private context used for internal data.
Definition avcodec.h:478
void * priv_data
Definition avcodec.h:470
void * hwaccel_priv_data
hwaccel-specific private data
Definition internal.h:130
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition frame.h:493
int width
Definition frame.h:544
int height
Definition frame.h:544
This struct aggregates all the (hardware/vendor-specific) "high-level" state, i.e.
Definition hwcontext.h:63
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
AVRefStructPool is an API for a thread-safe pool of objects managed via the RefStruct API.
Definition refstruct.c:183
VkImageLayout layout[AV_NUM_DATA_POINTERS]
VkAccessFlagBits2 access[AV_NUM_DATA_POINTERS]
Updated after every barrier.
int need_align
Definition dpx.h:70
void * hwaccel_picture_private
Definition dpx.h:62
AVFrame * frame
Definition dpx.h:61
int packing
Definition dpx.h:65
int endian
Definition dpx.h:67
enum AVPixelFormat pix_fmt
Definition dpx.h:63
int unpadded_10bit
Definition dpx.h:69
int components
Definition dpx.h:68
int stride
Definition dpx.h:66
AVRefStructPool * frame_data_pool
Definition vulkan_dpx.c:45
FFVulkanShader shader
Definition vulkan_dpx.c:44
FFVulkanDecodePicture vp
Definition vulkan_dpx.c:40
size_t size
Definition vulkan.h:98
VkCommandBuffer buf
Definition vulkan.h:142
FFVulkanDecodeShared * shared_ctx
uint32_t lg_size[3]
Definition vulkan.h:219
#define av_mallocz(s)
#define av_freep(p)
#define src
Definition vp8dsp.c:248
static char buffer[20]
Definition seek.c:32
int size
RefStruct is an API for creating reference-counted objects with minimal overhead.
Definition refstruct.h:58
@ FF_VK_REP_NATIVE
Definition vulkan.h:439
#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_count_images(AVVkFrame *f)
Definition vulkan.h:356
int ff_vk_update_thread_context(AVCodecContext *dst, const AVCodecContext *src)
Synchronize the contexts between 2 threads.
int ff_vk_decode_init(AVCodecContext *avctx)
Initialize decoder.
int ff_vk_frame_params(AVCodecContext *avctx, AVBufferRef *hw_frames_ctx)
Initialize hw_frames_ctx with the parameters needed to decode the stream using the parameters from av...
int ff_vk_decode_add_slice(AVCodecContext *avctx, FFVulkanDecodePicture *vp, const uint8_t *data, size_t size, int add_startcode, uint32_t *nb_slices, const uint32_t **offsets)
Add slice data to frame.
void ff_vk_decode_free_frame(AVHWDeviceContext *dev_ctx, FFVulkanDecodePicture *vp)
Free a frame and its state.
int ff_vk_decode_uninit(AVCodecContext *avctx)
Free decoder.
const unsigned char ff_dpx_unpack_comp_spv_data[]
static void vk_dpx_free_frame_priv(AVRefStructOpaque _hwctx, void *data)
Definition vulkan_dpx.c:325
static int vk_dpx_end_frame(AVCodecContext *avctx)
Definition vulkan_dpx.c:99
const unsigned int ff_dpx_copy_comp_spv_len
const FFVulkanDecodeDescriptor ff_vk_dec_dpx_desc
Definition vulkan_dpx.c:34
const unsigned char ff_dpx_copy_comp_spv_data[]
const unsigned int ff_dpx_unpack_comp_spv_len
static int vk_dpx_decode_slice(AVCodecContext *avctx, const uint8_t *data, uint32_t size)
Definition vulkan_dpx.c:80
static int init_shader(AVCodecContext *avctx, FFVulkanContext *s, FFVkExecPool *pool, FFVulkanShader *shd, int bits)
Definition vulkan_dpx.c:216
static int vk_decode_dpx_init(AVCodecContext *avctx)
Definition vulkan_dpx.c:286
static void vk_decode_dpx_uninit(FFVulkanDecodeShared *ctx)
Definition vulkan_dpx.c:275
static int vk_dpx_start_frame(AVCodecContext *avctx, const AVBufferRef *buffer_ref, const uint8_t *buffer, uint32_t size)
Definition vulkan_dpx.c:58
#define FF_VK_EXT_EXTERNAL_HOST_MEMORY