gfx: caching + offscreen infrastructure (pre-scene, from #2109) - #2119
Open
jcelerier wants to merge 7 commits into
Open
gfx: caching + offscreen infrastructure (pre-scene, from #2109)#2119jcelerier wants to merge 7 commits into
jcelerier wants to merge 7 commits into
Conversation
jcelerier
force-pushed
the
planc/gfx-infra
branch
from
July 17, 2026 11:58
1228382 to
1b6651e
Compare
jcelerier
added a commit
that referenced
this pull request
Jul 17, 2026
test_unit_gfx_assettable: AssetTable CPU logic + TextureLoader upload paths on QRhi's Null backend (no GPU needed). tests/hardware/: capability-probe framework (AJA/DeckLink/Magewell/PipeWire/ display) + ScoreHardwareTests.cmake — gated, run only on capture rigs. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014rZgzE8JjWvHDtaVUhxpLE
jcelerier
force-pushed
the
planc/gfx-infra
branch
from
July 17, 2026 14:10
1b6651e to
08516ad
Compare
jcelerier
added a commit
that referenced
this pull request
Jul 17, 2026
FIX-ISF (libisf/src/isf.cpp — applies on top of this branch's ISF/CSF feature rework, hence #2120 not #2119): - write_isf: seekp(0,end)-before-tellp corrupted the emitted descriptor - use-after-move on m_sourceVertex -> guard with .empty() - parse_shadertoy_json: GLSL45 preludes + iMouse vec4(0,0,0,0) - glsl_sandbox: duplicate-TIME uniform guard - replace_identifier: word-boundary match Tests: test_unit_isf_importers (all 5 importer branches); golden-image render regression (16 pinned JS-corpus cases, llvmpipe, SSIM/PSNR); timeline-driven scenario ramp; gfx resource/leak soak (DISABLED — guards a still-unfixed render-clock teardown UAF); live-edit churn corpus. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014rZgzE8JjWvHDtaVUhxpLE
jcelerier
added a commit
that referenced
this pull request
Jul 17, 2026
FIX-ENC: - NV12.hpp: UV plane encodes into an R8 target (16-byte-tight rows), was mis-sized producing garbage chroma on readback - YUVPlanar.hpp: p420_10 -> RGBA8-packed 16-bit LE on the Qt<6.10 GL path Tests: test_unit_video_pixel_format (pixfmt plane math + avutil mapping); test_integration_encoder_matrix (every encoder on a real QRhi backend, byte-checked); test_regression_offscreen_teardown (full-app offscreen render + /stop + /exit exits 0 — guards 1228382 #2119 + 32ad555 #2121 teardown UAFs); VideoDecoderTester + video-decoder-sweep.sh; EncoderTester ctest. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014rZgzE8JjWvHDtaVUhxpLE
jcelerier
added a commit
that referenced
this pull request
Jul 17, 2026
An unconfigured Text process rendered nothing: the UBO default position was
{0.5,0.5} (TextNode.hpp), a clip-space offset added to the text quad in the
vertex shader, which shoved the default text ~half a screen up+right — off the
top edge — until Position was manually set. Default to {0,0} (screen centre).
Found + verified by the P3-text render harness (untouched Text now renders
1508 visible px; the harness's default-visibility check is a hard assertion).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014rZgzE8JjWvHDtaVUhxpLE
jcelerier
added a commit
that referenced
this pull request
Jul 17, 2026
FIX-ISF (libisf/src/isf.cpp — applies on top of this branch's ISF/CSF feature rework, hence #2120 not #2119): - write_isf: seekp(0,end)-before-tellp corrupted the emitted descriptor - use-after-move on m_sourceVertex -> guard with .empty() - parse_shadertoy_json: GLSL45 preludes + iMouse vec4(0,0,0,0) - glsl_sandbox: duplicate-TIME uniform guard - replace_identifier: word-boundary match Tests: test_unit_isf_importers (all 5 importer branches); golden-image render regression (16 pinned JS-corpus cases, llvmpipe, SSIM/PSNR); timeline-driven scenario ramp; gfx resource/leak soak (DISABLED — guards a still-unfixed render-clock teardown UAF); live-edit churn corpus. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014rZgzE8JjWvHDtaVUhxpLE
jcelerier
added a commit
that referenced
this pull request
Jul 17, 2026
Headless llvmpipe golden+value harness for the Gfx::Text process: grabs the untouched-defaults frame (hard off-screen-default visibility assertion — guards the #2119 default-position fix), then live-edits text/font/size/position/scale/ color over OSC /script and asserts pixel VALUES per case (coverage, bbox ordering across sizes, centroid movement, channel dominance, blank empty string, unicode/CJK/tofu/2000-char) + golden refs (compare.py strict). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014rZgzE8JjWvHDtaVUhxpLE
jcelerier
added a commit
that referenced
this pull request
Jul 17, 2026
FIX-ENC: - NV12.hpp: UV plane encodes into an R8 target (16-byte-tight rows), was mis-sized producing garbage chroma on readback - YUVPlanar.hpp: p420_10 -> RGBA8-packed 16-bit LE on the Qt<6.10 GL path Tests: test_unit_video_pixel_format (pixfmt plane math + avutil mapping); test_integration_encoder_matrix (every encoder on a real QRhi backend, byte-checked); test_regression_offscreen_teardown (full-app offscreen render + /stop + /exit exits 0 — guards 1228382 #2119 + 32ad555 #2121 teardown UAFs); VideoDecoderTester + video-decoder-sweep.sh; EncoderTester ctest. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014rZgzE8JjWvHDtaVUhxpLE
jcelerier
force-pushed
the
planc/gfx-infra
branch
from
July 18, 2026 13:37
6470247 to
2676d67
Compare
jcelerier
force-pushed
the
planc/gfx-infra
branch
2 times, most recently
from
July 19, 2026 03:14
387b649 to
65ff611
Compare
jcelerier
force-pushed
the
planc/gfx-infra
branch
6 times, most recently
from
July 25, 2026 11:53
2b108de to
51e0e1b
Compare
jcelerier
force-pushed
the
planc/gfx-infra
branch
from
July 29, 2026 18:21
51e0e1b to
b003872
Compare
jcelerier
force-pushed
the
planc/gfx-infra
branch
5 times, most recently
from
July 31, 2026 00:17
3536464 to
3e157ee
Compare
jcelerier
force-pushed
the
split/gfx-fixes-and-formats
branch
from
August 17, 2026 02:51
2f72efa to
c6b09de
Compare
jcelerier
force-pushed
the
planc/gfx-infra
branch
from
August 17, 2026 02:51
98f2876 to
1018e16
Compare
jcelerier
force-pushed
the
split/gfx-fixes-and-formats
branch
from
August 17, 2026 13:30
c6b09de to
5552446
Compare
jcelerier
force-pushed
the
planc/gfx-infra
branch
2 times, most recently
from
August 17, 2026 13:51
07f5ae3 to
c8df254
Compare
jcelerier
force-pushed
the
split/gfx-fixes-and-formats
branch
2 times, most recently
from
August 17, 2026 19:04
6c3686a to
f5e872d
Compare
jcelerier
force-pushed
the
planc/gfx-infra
branch
from
August 17, 2026 19:04
c8df254 to
1f97380
Compare
jcelerier
force-pushed
the
split/gfx-fixes-and-formats
branch
from
August 18, 2026 00:44
f5e872d to
ee75df3
Compare
jcelerier
force-pushed
the
planc/gfx-infra
branch
from
August 18, 2026 00:44
1f97380 to
e1221b7
Compare
jcelerier
force-pushed
the
split/gfx-fixes-and-formats
branch
from
August 18, 2026 01:30
ee75df3 to
7bc0e11
Compare
jcelerier
force-pushed
the
planc/gfx-infra
branch
from
August 18, 2026 01:30
e1221b7 to
f2f8f5e
Compare
jcelerier
force-pushed
the
split/gfx-fixes-and-formats
branch
from
August 19, 2026 01:44
7bc0e11 to
525b3ff
Compare
jcelerier
force-pushed
the
planc/gfx-infra
branch
from
August 19, 2026 01:44
f2f8f5e to
8460bf9
Compare
jcelerier
force-pushed
the
split/gfx-fixes-and-formats
branch
from
August 19, 2026 02:03
525b3ff to
d427269
Compare
jcelerier
force-pushed
the
planc/gfx-infra
branch
from
August 19, 2026 02:03
8460bf9 to
d986f38
Compare
jcelerier
force-pushed
the
split/gfx-fixes-and-formats
branch
from
August 19, 2026 03:14
d427269 to
b612cfa
Compare
jcelerier
force-pushed
the
planc/gfx-infra
branch
from
August 19, 2026 03:14
d986f38 to
2ef4db9
Compare
jcelerier
force-pushed
the
split/gfx-fixes-and-formats
branch
from
August 19, 2026 03:35
b612cfa to
b5eebc2
Compare
jcelerier
force-pushed
the
planc/gfx-infra
branch
from
August 19, 2026 03:35
2ef4db9 to
9bc5a91
Compare
jcelerier
force-pushed
the
split/gfx-fixes-and-formats
branch
from
August 19, 2026 06:19
b5eebc2 to
ca1a743
Compare
jcelerier
force-pushed
the
planc/gfx-infra
branch
from
August 19, 2026 06:19
9bc5a91 to
dba7e4b
Compare
jcelerier
force-pushed
the
split/gfx-fixes-and-formats
branch
from
August 19, 2026 12:20
ca1a743 to
a6fb926
Compare
test_unit_gfx_assettable: AssetTable CPU logic + TextureLoader upload paths on QRhi's Null backend (no GPU needed). tests/hardware/: capability-probe framework (AJA/DeckLink/Magewell/PipeWire/ display) + ScoreHardwareTests.cmake — gated, run only on capture rigs. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014rZgzE8JjWvHDtaVUhxpLE
An unconfigured Text process rendered nothing: the UBO default position was
{0.5,0.5} (TextNode.hpp), a clip-space offset added to the text quad in the
vertex shader, which shoved the default text ~half a screen up+right — off the
top edge — until Position was manually set. Default to {0,0} (screen centre).
Found + verified by the text-render harness (untouched Text now renders
1508 visible px; the harness's default-visibility check is a hard assertion).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014rZgzE8JjWvHDtaVUhxpLE
Replace the timer->set<OutputNode*> map with RenderClock: one TimerClock per distinct manualRenderingRate owning the coalesced set of outputs it drives, and a DisplayVSyncClock wrapping the swap-chain vsync callback. Behaviour is unchanged; the clocks are torn down before the timer pool is rebuilt so their dtors release the shared timers back to a still-live pool. The teardown paths added earlier in this branch already unregister outputs from the render clocks, but the abstraction they use landed further up the series; this brings it down to where it is first needed. Dropping an output's edges on teardown needs Graph::removeNodeAndEdges, which is part of the incremental render-list rework, so that call moves to the commit that introduces it. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014rZgzE8JjWvHDtaVUhxpLE
In VSync mode the on-screen render loop re-drives itself solely through QWindow::requestUpdate(). On xcb that is an unconditional timer, so the loop self-heals. On Wayland requestUpdate() is frame-callback gated: if the compositor withholds a frame callback past QT_WAYLAND_FRAME_CALLBACK_TIMEOUT (default 100ms) -- occluded window, blanked/DPMS output, another surface on top, or heavy per-frame work -- Qt marks the window inexposed and the loop, having no other driver, produces no frames. The render itself is fine: an offscreen readback of the same frame returns correct pixels, so the symptom is a black on-screen window despite correct rendering. Confirmed by flipping only the VSync setting on a KDE-Wayland session, and by a minimal QRhi repro whose requestUpdate loop dies under a forced 1ms frame-callback timeout while a timer-driven loop is unaffected. Gate the vsync loop off when the Qt platform is Wayland so it takes the timer path. The compositor supplies frame pacing there, so no tearing results from dropping swap-chain vsync. xcb, eglfs and the embedded backends are unchanged. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014rZgzE8JjWvHDtaVUhxpLE
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.
Extracts the self-contained gfx infrastructure from #2109 that compiles against master independently of the coupled "scene concept" rework. Landing these first shrinks the eventual scene-rework PR and makes it reviewable.
These are additive: new files, wired into CMake, not yet referenced by any consumer — the scene rework (a later PR) wires them up. They are included here so that PR is smaller and each piece can be reviewed on its own.
Stacked on #2117 (test infrastructure); will retarget to master once #2117 merges.
Commits
AssetTable+TextureLoader— a shared cache for decoded image/texture assets (Gfx/AssetTable.*,Gfx/Graph/TextureLoader.*). Depends only onQImage/QRhi/ossia::hash_map.AssetTableentries evictable (follow-up to the above).OffscreenDevice+RhiPreviewWidget+ a Metal buffer-copy backend — offscreen QRhi rendering + a preview widget, using the existingGraph/GfxContext/BackgroundNodeAPIs.Deferred to the scene-rework PR (Plan D)
GpuResourceRegistry+OffsetAllocatorsubmodule) — hard-depends onSceneGPUState.hpp, which the scene concept introduces.Validation
ctest: 17/17 (no regression; the additions are not yet on any exercised path).🤖 Generated with Claude Code