Repository navigation
virgl: 2D_ARRAY lookups on samplers without a view read a 2D texture (motion-adaptive deinterlacing) - #615
Merged
Conversation
gillesgoetsch
added a commit
that referenced
this pull request
Oct 29, 2026
Mesa's deinterlacer declares its samplers without views (SAMP only) and reads the decoded pictures, plain 2D textures, with 2D-array lookups. virgl-shader-array-sampler-2d-view.patch maps such lookups to 2D only for samplers declared with a view, so the Mac's GL read zeros. A renderer test shows it (test-const-ubo.c case 25: black on the current runtime); the fix is #615, not yet measured in a VM. The bullet said the Mac's GL did not sample the deinterlacer's own buffer: wrong. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This was referenced Oct 29, 2026
test-const-ubo.c case 25: a fragment shader that declares only SAMP[0] (no SVIEW) and looks up 2D_ARRAY, as Mesa's motion-adaptive deinterlacer (vl_deint_filter.c) reads the decoded pictures, with a plain 2D view bound; between two of its draws one with the declared view of case 23; then a real 2D array in that slot, read at layer 1. On the current runtime stripes 0 and 2 read black (0xff000000): the 2D-view patch only maps samplers declared with a view. The fix follows. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Mesa's motion-adaptive deinterlacer (vl_deint_filter.c) declares its samplers without views (SAMP[0..3], no SVIEW) and reads the decoded pictures, plain 2D textures, with 2D_ARRAY lookups. The 2D-view patch mapped such lookups to 2D only for samplers declared 2D_ARRAY with a view, so here GL got a sampler2DArray on a 2D texture and read zeros (QEMU's log: "GLD_TEXTURE_INDEX_2D_ARRAY is unloadable ... using zero texture"): every deinterlaced picture was Y=U=V=0, green (mpv's vavpp default, FFmpeg's deinterlace_vaapi). In a shader that declares no sampler views, a 2D_ARRAY lookup now counts as the 2D_ARRAY declaration of that sampler, so the key bit and the 2D form follow as for declared views. Real 2D arrays are not touched (the key bit is set only for a plain 2D view). Tests: test-const-ubo.c case 25 (black before, right after; a real 2D array still reads its layer), run-regressions.py all OK. Not yet measured in a VM (motion-adaptive deinterlacing in mpv/FFmpeg). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ys green The VM row of #615 (Mac mini M4, a hidden test VM, published 3.2.12 before, this branch after): FFmpeg's deinterlace_vaapi and mpv's vavpp no longer give green pictures on interlaced video coded as frames, and QEMU's log has no 'unloadable' line. H.264 coded interlaced (x264 MBAFF, 1080i and 576i) is green in every VA-API path on both runtimes: VideoToolbox refuses most of its pictures (-8969). Listed as its own known issue, with CPU decoding as the way round it.
gillesgoetsch
force-pushed
the
virgl-samp-array
branch
from
October 29, 2026 17:23
662ce50 to
4257d4b
Compare
… cause not known GStreamer's vapostproc is out of the fixed list (no row ran GStreamer, and the element that deinterlaces is vadeinterlace): vadeinterlace with method=adaptive is named as the same Mesa path, not measured. mpv against the test pattern: 33.0 dB (this branch, second field) and 34.2 dB (mpv's CPU deinterlacer, first field), 3.2.12 9.9 dB, from work/vavpp-row/kit/mac/psnr-truth.sh with the colours as mpv shows the clip (BT.709). The first numbers (26.2 / 26.4 / 9.4 dB) compared against testsrc2 drawn as RGB, whose colours are not mpv's. Interlaced H.264: "most" now rests on the green-frame counts (bob 30 to 36 of 50, was 30 to 35), the -8969 lines are capped at 20 per stream by the runtime, and the cause is not known yet.
…ommand Drops GStreamer's vapostproc (not measured), uses psnr-truth.sh's 33.0 and 34.2 dB (3.2.12 9.9 dB), and words interlaced H.264 by its green-frame counts (30 to 36 of 50 with bob), cause not known yet.
This was referenced Oct 29, 2026
Merged
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Lane v4l2-vavpp (re-review of #613), VM row by lane vavpp-row. Rebased on main c29fd80 (3.2.12). Not merged by the lane.
What was wrong. Mesa's motion-adaptive deinterlacer (
vl_deint_filter.c, the same in Mesa 26.2.4 and 26.2.5) declares its samplers without views (DCL SAMP[0..3], noSVIEW) and reads the decoded pictures, plain 2D textures, with2D_ARRAYlookups.virgl-shader-array-sampler-2d-view.patchmaps a2D_ARRAYsampler on a plain 2D view tosampler2Donly where the shader declares the view2D_ARRAY(Mesa's video compositor does). Here nothing was declared, so GL got asampler2DArrayon a 2D texture and read zeros (QEMU's log, once:GLD_TEXTURE_INDEX_2D_ARRAY is unloadable ... using zero texture). Every deinterlaced picture was Y=U=V=0: green in mpv's--vf=vavppdefault and FFmpeg'sdeinterlace_vaapi(motion-adaptive), also with Mesa's VA driver alone. This is OmacVM's runtime, not Mesa.Fix. In a shader that declares no sampler views, a
2D_ARRAYlookup counts as the2D_ARRAYdeclaration of that sampler (samplers_2d_array_declared), so the shader info, the key bit and the 2D form follow as for declared views. The key bit is still set only for a plain 2D view, so real 2D arrays keepsampler2DArray. Not for samplers indexed indirectly (as before).Test.
Tests/virgl/test-const-ubo.ccase 25 (Apple's software renderer, never the GPU): a SAMP-only2D_ARRAYlookup on a 2D view, then the declared-view shader of case 23, then the SAMP-only one again, then a real two-layer 2D array in that slot read at layer 1.run-regressions.pyon this branch: all OK (case 25 in all three constant modes, 24 random seeds the same). Built from the 3.2.12 set's patched virglrenderer 1.3.0 with this patch swapped in; the patch applies in the chain without offset or fuzz and gives the same tree.SHA256SUMSupdated.VM row (2026-10-29, Mac mini M4, macOS 27). One hidden test VM (APFS clone of a kept test VM, 4 CPU / 2 GB, Update VM to 3.2.12 by this branch's app; Mesa 26.2.5, FFmpeg 9.0.2, mpv 0.41, Chromium 153, Chrome 156), started by the test-identity app: first the published 3.2.12 (relabeled, c29fd80), then a build of this branch (58908ea, runtime from source, build tests passed). Clips made in the VM with FFmpeg from
testsrc2at 50 fields/s woven bytinterlace=interleave_topinto 25 fps, H.264 (x264):c10801920x1080 coded as frames,i10801920x1080 andi576720x576 coded interlaced (MBAFF, tff). References: FFmpeg's CPUbwdifandyadif(send_frame, tff, every frame).(1) FFmpeg
deinterlace_vaapi(rate frame) on VA-API decoding, OmacVM's driver (the VM's default; Mesa's driver alone the same green before), read back as NV12; PSNR average over the frames, best of offsets 0-3:28.14 dB compares different fields: the clip is flagged progressive, and FFmpeg's
deinterlace_vaapitakes a frame without the top-field-first flag as bottom field first and, at rate frame, outputs the bottom field (the second, 20 ms later), whilebwdif(parity tff, send_frame) outputs the top one. So it is a low mark, not the deinterlacer's quality.(2) mpv
--gpu-api=opengl --vo=gpu, full screen, paused at 1.0 s, mpv'sscreenshot-to-file(video and window):--hwdec=vaapi --vf=vavpp("Selected deinterlacing algorithm: 3") and--hwdec=vaapi --deinterlace=yesgive the same picture. c1080 on 3.2.12: all green (Y/U/V 55/106/100 in the PNG: Y=U=V=0 through BT.709), 9.9 dB against mpv's CPU deinterlacer (--hwdec=no --deinterlace=yes); on this branch: the right picture (28.7 dB against the CPU deinterlacer, which shows the other field), testsrc2's clock reads 1.020 / frame 51 without combing (the second field; the CPU deinterlacer shows the first, 1.000 / 50; without deinterlacing the digits are combed). Against testsrc2's own picture of the field each shows, in the colours mpv shows the clip in (its log:bt.709/bt.709/bt.1886/limited): this branch 33.0 dB (second field), mpv's CPU deinterlacer 34.2 dB (first field), 3.2.12 9.9 dB. Command: work/vavpp-row/kit/mac/psnr-truth.sh (Mac FFmpeg 9.0.1,testsrc2=size=1920x1080:rate=50, frame 50 or 51,format=yuv420p,scale=in_color_matrix=bt709:out_color_matrix=bt601,format=rgb24,format=yuv444pagainst the screenshot asyuv444p,psnr); output work/vavpp-row/out/psnr-truth.txt. An earlier version of this PR gave 26.2 / 26.4 / 9.4 dB: that is the same script's other reference, testsrc2 drawn asrgb24, whose colours are not mpv's (its lines are in the same file and match the first run to the digit, out/psnr-truth-first.txt).(3) qemu.log:
GLD_TEXTURE_INDEX_2D_ARRAY is unloadableonce on 3.2.12, none on this branch. No new kind of line: the same kinds on both (342vt-video: decode failed: -8969, 18decode failed: 1, both capped, below;video: zero-copy failed, copying this frame with the CPU1 and 3 times).(4) Unchanged, row for row: video-geometry (mpv, mpv gpu-next, Chrome 156 on Wayland; H.264, VP9, HEVC at 1920x1080, 1280x720, 854x480, 640x360, 1000x562) 45/45 exact on both; VPP rows (
scale_vaapi, convertingvaGetImageon 8 clips, alsoOMACVM_VA_LOGICAL=0) 32/32 exact and texels 16/16 exact on both; glmark2--validate11 Success, 0 Failure, 16 scenes, score 2659 / 2636; Chromium WebGL1/2 60 s each 3594/3599 and 3604/3601 frames, no context lost; no host GPU fault, no core in the VM, tccd "Notifying" 0.Not fixed here (found by these rows, the same on 3.2.12): H.264 coded interlaced (
i1080,i576) is green in every VA-API path, with or without deinterlacing. Most frames: FFmpeg's bob (a plain copy in Mesa 26.2) has 30-36 of 50 frames green on both runtimes; motion-adaptive 47 of 47 on 3.2.12, 32-37 of 47 here; mpv's vavpp oni576is still all green on this branch (mpv's frame at 1.0 s). VideoToolbox returns errors on these streams (vt-video: decode failed: -8969, its "bad data"): qemu.log has 20decode failedlines per run of these two clips (19 -8969, 1 status 1; 18 runs per side: 12 FFmpeg, 6 mpv; none in thec1080runs), but 20 is the runtime's log cap (virgl-videotoolbox-decode-async.patchlogs the first 20 failures per stream), so the log does not say how many pictures failed. Cause not known when this was written; found later and fixed in #619 (the Mac's hardware decoder refuses interlaced H.264, the VA shim now refuses such pictures). At the 3.2.13 merge this PR's interlaced CHANGELOG sentence and docs item were replaced by #619's.Raw rows: work/vavpp-row/out (summary.txt, before/, after/: deint.jsonl, mpv.jsonl + screenshots, vg.*, vpp.jsonl, glmark2.txt, chromium.txt, qemu.log). Kit: work/vavpp-row/kit.
Docs:
docs/architecture/graphics.mdrow;docs/video-decode.md: the deinterlacing known issue says fixed since 3.2.13 with the rows above (GStreamer'svadeinterlacewithmethod=adaptivenamed as the same Mesa path, not measured; no row ran GStreamer, andvapostprocis not listed), and a new known issue for H.264 coded interlaced; CHANGELOG 3.2.13 (unreleased).Track: work/tracks/v4l2-vavpp-odd.md (VM row at its end).