PR #25463 opened by widlarizer
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/25463
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/25463.patch
# Summary of changes
## Context
I discovered H264 encoding errors caused by ffmpeg on a meteor lake laptop
while debugging mesa vulkan encode issues for i915/xe. It turns out to be a
cache coherence issue. Claude Opus 5.5 was used in debugging the problem and
producing the patch but I kept it on a tight leash.
## Code
The packet buffer can be non-coherent (e.g. Intel non-LLC GPUs). The
headers written by the CPU were never flushed before submission, and
the readback flushed instead of invalidating. On Meteor Lake this
corrupted h264_vulkan and hevc_vulkan output at random.
## Tests
I'm not including any tests. Open to advice on this.
# Reproducer
## Environment
- ffmpeg 9.0 and master `46f23be8b197` (2026-10-17). Master still requests
`HOST_CACHED` for the packet buffer whenever the device has a cached type
(`s->host_cached_flag`), and on this GPU that type is non-coherent.
- Intel Meteor Lake (8086:7d55), i915, Linux 6.18.58
- Mesa ANV main `18879c94176c`
- ANV memory types on this machine:
- `DEVICE_LOCAL | HOST_VISIBLE | HOST_COHERENT`
- `DEVICE_LOCAL | HOST_VISIBLE | HOST_CACHED` (non-coherent),
`nonCoherentAtomSize` 64
## Script
```sh
ffmpeg -f lavfi -i "testsrc2=s=1920x1080:r=100,noise=alls=12:allf=t+u"
-frames:v 100 \
-pix_fmt nv12 -f rawvideo src.yuv
for i in 1 2 3; do
ffmpeg -init_hw_device vulkan=vk:0 -filter_hw_device vk \
-f rawvideo -pix_fmt nv12 -s 1920x1080 -r 100 -stream_loop 2 -i src.yuv \
-vf format=nv12,hwupload -c:v h264_vulkan -bf 0 -g 1000 \
-rc_mode cbr -b:v 20M -maxrate 20M -bufsize 20M -y out$i.h264
md5sum out$i.h264
ffmpeg -v error -i out$i.h264 -f null - 2>&1 | wc -l # decode errors
done
```
##
>From 99c61e23b396c59013cdaf64441e311f0b07a049 Mon Sep 17 00:00:00 2001
From: "Emil J. Tywoniak" <[email protected]>
Date: Sun, 25 Oct 2026 22:56:31 +0100
Subject: [PATCH] avcodec/vulkan_encode: flush and invalidate non-coherent
packet buffers
The packet buffer can be non-coherent (e.g. Intel non-LLC GPUs). The
headers written by the CPU were never flushed before submission, and
the readback flushed instead of invalidating. On Meteor Lake this
corrupted h264_vulkan and hevc_vulkan output at random.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
---
libavcodec/vulkan_encode.c | 43 +++++++++++++++++---------------------
1 file changed, 19 insertions(+), 24 deletions(-)
diff --git a/libavcodec/vulkan_encode.c b/libavcodec/vulkan_encode.c
index 9d3c9b04c57..8b61c76abbf 100644
--- a/libavcodec/vulkan_encode.c
+++ b/libavcodec/vulkan_encode.c
@@ -337,6 +337,10 @@ static int vulkan_encode_issue(AVCodecContext *avctx,
}
}
+ /* Flush the headers written above if needed */
+ if (encode_info.dstBufferOffset)
+ RET(ff_vk_flush_buffer(&ctx->s, sd_buf, 0, VK_WHOLE_SIZE, 1));
+
vp->slices_offset = encode_info.dstBufferOffset;
/* Align buffer size to the nearest lower alignment requirement. */
@@ -492,6 +496,7 @@ static int vulkan_encode_output(AVCodecContext *avctx,
FFHWBaseEncodePicture *base_pic, AVPacket *pkt)
{
VkResult ret;
+ int err, offs;
FFVulkanEncodePicture *vp = base_pic->priv;
FFVulkanEncodeContext *ctx = avctx->priv_data;
FFHWBaseEncodeContext *base_ctx = &ctx->base;
@@ -520,32 +525,22 @@ static int vulkan_encode_output(AVCodecContext *avctx,
return AVERROR_EXTERNAL;
}
- /* Invalidate buffer if needed */
- if (!(sd_buf->flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)) {
- FFVulkanFunctions *vk = &ctx->s.vkfn;
- VkMappedMemoryRange invalidate_buf;
-
- int offs = vp->slices_offset;
- /* If the non-coherent alignment is greater than the bitstream buffer
- * offset's alignment, and the offs value is not aligned already,
- * align it to the previous alignment point. */
- if (ctx->s.props.properties.limits.nonCoherentAtomSize >
- ctx->caps.minBitstreamBufferOffsetAlignment && offs &&
- (FFALIGN(offs, ctx->s.props.properties.limits.nonCoherentAtomSize)
!= offs)) {
- offs -= ctx->s.props.properties.limits.nonCoherentAtomSize;
- offs = FFALIGN(FFMAX(offs, 0),
ctx->s.props.properties.limits.nonCoherentAtomSize);
- }
-
- invalidate_buf = (VkMappedMemoryRange) {
- .sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,
- .memory = sd_buf->mem,
- .offset = offs,
- .size = VK_WHOLE_SIZE,
- };
-
- vk->FlushMappedMemoryRanges(ctx->s.hwctx->act_dev, 1, &invalidate_buf);
+ /* If the non-coherent alignment is greater than the bitstream buffer
+ * offset's alignment, and the offs value is not aligned already,
+ * align it to the previous alignment point. */
+ offs = vp->slices_offset;
+ if (ctx->s.props.properties.limits.nonCoherentAtomSize >
+ ctx->caps.minBitstreamBufferOffsetAlignment && offs &&
+ (FFALIGN(offs, ctx->s.props.properties.limits.nonCoherentAtomSize) !=
offs)) {
+ offs -= ctx->s.props.properties.limits.nonCoherentAtomSize;
+ offs = FFALIGN(FFMAX(offs, 0),
ctx->s.props.properties.limits.nonCoherentAtomSize);
}
+ /* Invalidate buffer if needed */
+ err = ff_vk_flush_buffer(&ctx->s, sd_buf, offs, VK_WHOLE_SIZE, 0);
+ if (err < 0)
+ return err;
+
if (vp->non_independent_frame) {
av_assert0(!ctx->prev_buf_ref);
size_t prev_buf_size = vp->slices_offset + query_data[0] +
query_data[1];
--
2.54.0
_______________________________________________
ffmpeg-devel mailing list -- [email protected]
To unsubscribe send an email to [email protected]