split/gpu interop#2078
Open
jcelerier wants to merge 101 commits into
Open
Conversation
jcelerier
commented
Jun 14, 2026
Member
- isf: TEX_DIMENSIONS_3D / IMG_SIZE_3D aliases for 3D samplers
- isf: point3d_input AS_COLOR flag for color-swatch display
- isf: parse-time warning on unknown csf_image_input FORMAT
- isf: parser rework — top-level descriptors, uniform inputs, geometry AUXILIARY, vertex inputs
- 3rdparty: add OffsetAllocator submodule
- gfx: add AssetTable + TextureLoader for shared decoded-asset cache
- gfx: add GpuResourceRegistry — slab-allocated GPU arenas backed by OffsetAllocator
- gfx: add CameraMath / GpuTiming / VertexFallback helpers
- gfx: add IsfBindingsBuilder + PipelineStateHelpers
- gfx: add SceneGPUState — FlatScene + scene packer
- gfx: add OffscreenDevice + RhiPreviewWidget + Metal buffer-copy backend
- gfx: extend ISF / SimpleRenderedISF nodes for new ISF features
- csf: rework for scene-aware compute pipeline
- gfx: rework raw raster pipeline (MRT, AUXILIARY, EXECUTION_MODEL) and VSA
- gfx: refresh shared graph plumbing for incremental scene pipeline
- gfx: add ScenePreprocessorNode — scene_spec to flat draws + arena uploads
- gfx: add SceneFilterNode + FlattenedSceneFilterNode + MergeGeometriesNode
- avnd: split CpuFilter / CpuAnalysis lifecycle into init / initState / release
- avnd: add scene_port concept
- avnd: split GpuNode lifecycle and add scene_port storage helpers
- gfx: extend ShaderProgram for new ISF features
- gfx: refresh Filter / GeometryFilter / TexturePort for new pipeline
- gfx: refresh WindowDevice / Spout / Syphon / WindowCapture
- gfx: refresh GfxContext + window / screen / multiwindow nodes for incremental scene rebuild
- js: gpu node lifecycle rework with deterministic teardown
- wip: many bugfixes across the board
- build: more build fixes
- ci: fixes for older qt versions
- rhi: populate caps
- ci: try windows fixes
- gfx: restore PhongNode, still used by score-vfx-template
- gfx: keep TextureRenderTarget compatible with addons' aggregate init
- gfx: do not include mmsystem.h in CommonUBOs.hpp
- gfx: fix build with Qt < 6.9
- gfx: fix designator order after TextureRenderTarget reorder
- gfx: fix build with Qt 6.4
- gfx: more Qt 6.4 compatibility guards
- xcb: use EGL instead of GLX by default
- desktop: enforce desktop GL (Qt may pick GLES when we use a EGL surface)
- gpu: try to land a generalized abstraction for interop & RDMA
851f361 to
b1c6d32
Compare
…AUXILIARY, vertex inputs Top-level descriptors (PIPELINE_STATE, MULTIVIEW, EXECUTION_MODEL, EXTENSIONS, CLIP_DISTANCES / CULL_DISTANCES, DEPTH_LAYOUT). New input kinds: uniform_input (UBO INPUTS), per-input sampler_config (WRAP / FILTER / COMPARE / MIPS), audio_sampler_config. Storage / image / cubemap input extensions: PERSISTENT, IS_ARRAY, GENERATE_MIPS, cube/3D textures. Geometry input AUXILIARY: storage + sampled, persistent, is_uniform, depth companion, INDIRECT block. Per-pass: LAYER, Z, FORMAT, PIPELINE_STATE override. OUTPUTS: LAYERS, DEPTH, FORMAT, SAMPLES, CUBEMAP, GENERATE_MIPS, WIDTH/HEIGHT expressions. Vertex inputs: REQUIRED, DEFAULT, SEMANTIC, INTERPOLATION (with auto-flat for int/bool varyings). Bug fixes: mat3/mat4 attribute slot count, TYPES struct emission in BOTH stages, drop incorrect std430 padding heuristic that was breaking RawLight stride.
…remental scene rebuild
The encoder's Swizzle enum denotes the in-memory byte order of the RGBA8 output. Add the [A,R,G,B] order (needed for NTV2_FBF_RGBA, whose actual memory layout is A,R,G,B despite the name) and clarify that the names are memory orders, not AJA FBF names. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FnqYUYn7AVxBQFZywarDNT
New GPUVideoEncoder implementations for AJA framebuffer formats beyond the 8-bit RGB / UYVY / v210 / 10-bit-422-planar set: - PackedRGB.hpp: generic packed-pixel encoder generalising the V210 "one RGBA8 output texel == 4 destination row bytes" trick to any byte layout via a per-format rowByte(b) GLSL function. Factories for NTV2_FBF_10BIT_RGB, 10BIT_DPX (BE) / 10BIT_DPX_LE, 48BIT_RGB (full 16-bit), 12BIT_RGB_PACKED, 24BIT_RGB / 24BIT_BGR, and 10BIT_ARGB. Bit layouts verified against the SDK PackRGB10Bit* / Convert16BitARGBTo* / ConvertLine_8bitABGR_* helpers. - YUY2.hpp: 8-bit 4:2:2 YUY2 byte order (Y0,Cb,Y1,Cr). - YUVPlanar.hpp: generic 3-plane planar YCbCr, 8/10-bit x 4:2:2/4:2:0 (R8/R16 plane targets, Qt>=6.10). Validated round-trip on Kona5 12-bit firmware across GL/Vulkan/D3D11/D3D12: 10-bit RGB, both DPX, 12-bit (48-bit + packed), and 24-bit RGB/BGR all pass (42.8-43.6 dB). YUY2/10-bit-ARGB/planar encoders are correct but the Kona5 does not drive those framestore formats to SDI (card output limitation). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FnqYUYn7AVxBQFZywarDNT
The CPU-staging counterpart to GpuDirectOutput (and the output-direction
counterpart to HostPinnedRing): the path used whenever GPU-direct DMA isn't
available - the common case on consumer GPUs. It owns the full
"encode on GPU -> read back -> hand a host pointer to the card's DMA"
pipeline:
- the two double-buffered GPUVideoEncoders,
- a page-locked staging ring (vendor-pinned via VendorDmaRegistrar),
- the direct-DMA-from-readback fast path (page-lock the encoder readback
buffer when it's already byte-identical to the framestore, skipping the
per-frame memcpy),
- single-plane / planar staging, plus an optional vendor customStage hook
for special packing (e.g. v210 CPU pack for non-mod-6 widths).
Vendors supply only pin/unpin callbacks + per-frame submit/pacing, so
DeckLink / Magewell / Bluefish output can reuse this instead of
re-implementing the ring + readback + direct-DMA. VendorDmaRegistrar moved
to its own header so both output helpers share it without the GPU-direct
header's CUDA deps.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FnqYUYn7AVxBQFZywarDNT
Two shared seams lifted out of the AJA addon so DeckLink/Bluefish/
Magewell/Deltacast addons reuse them instead of re-deriving:
- makeWireEncoder(VideoPixelFormat) / makeWireComputeEncoder /
wireComputeSupports (encoders/WireEncoderFactory.hpp): the
RGBA->wire encoder switch, keyed on the neutral VideoPixelFormat
enum instead of a vendor format enum. Extended VideoPixelFormat
with the formats the existing encoders already produce (RGB24/BGR24,
ARGB10, DPX10/DPX10LE, RGB12P, RGB48, YUV420P10).
- PacedFramePump (interop/PacedFramePump.{hpp,cpp}): the lock-free
SPSC ring + clock-paced consumer thread + drain-to-newest +
drop/underrun accounting, generalised from AJAConsumerThread. The
vendor supplies three hooks: waitForTick / canAccept / submit.
Also adds the multi-vendor implementation map document.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FnqYUYn7AVxBQFZywarDNT
selectGpuDirectStrategy(cfg, candidates, onEngaged, onFailed) owns the DVP->Tier3->fallback init/log/release loop every output addon repeats. The per-vendor strategy classes stay in the addon (they hold the card handle + format); the addon passes factory thunks for the active backend. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FnqYUYn7AVxBQFZywarDNT
Shared base for professional capture-card INPUT nodes (AJA, and future DeckLink/Bluefish/Deltacast/Magewell). DMACaptureRenderer owns all the generic machinery — mesh/UBO setup, decoder init, GpuDirectCaptureStrategy init with CPU-staging fallback, the zero-copy texture swap, defaultPassesInit, the per-frame slot-ring poll + acquire/release bracket, and teardown. The vendor supplies a DMACaptureBackend: open the device, report geometry + colour metadata, build the decoder for its wire format, pick the GPU-direct strategy (+ CPU fallback), and run the capture thread feeding the slot ring. This is the input-side counterpart to the output seams (HostStagedOutput / GpuDirectStrategy / PacedFramePump). It is deliberately NOT a universal "video input" base: the AVFrame-upload path (camera/NDI, VideoNodeRenderer) and the shared-texture path (Spout/Syphon) are different frame-delivery models; this base is specifically the DMA-capture-card family. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FnqYUYn7AVxBQFZywarDNT
Record the implemented shared seams (#3 makeWireEncoder, #2 PacedFramePump, #4 selectGpuDirectStrategy, DMACaptureInputNode/DMACaptureBackend), the naming/scoping decisions (DMACaptureInputNode not VideoInputNode; no monolithic VendorIoBackend), and the vendor authoring surface. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FnqYUYn7AVxBQFZywarDNT
Single source of truth for the overlap between the capture-card wire-format enum and libav's AVPixelFormat. toAVPixelFormat / fromAVPixelFormat map the buffer formats that have byte-identical twins (planar/semi-planar YUV, packed 8-bit + 16-bit RGB, grey, UYVY/YUYV/YVYU) and return NONE/Unknown for the wire-only packed formats FFmpeg models as codecs rather than pixel formats (v210, v216, r210, DPX 10/12, 12-bit packed RGB, A2-ARGB10). Lets the capture path derive a VideoPixelFormat from the AVPixelFormat that Video::ImageFormat already carries, and lets vendor tables interop with the libav-based decoder/encoder paths without each site re-deriving the mapping. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FnqYUYn7AVxBQFZywarDNT
…innedFormat
- decoders/WireDecoderFactory.hpp: makeWireDecoder(VideoPixelFormat, ImageFormat&)
— the capture-side symmetric of makeWireEncoder, over the real GPUVideoDecoder
classes. Vendor capture backends stop hand-rolling the format->decoder switch.
- Remove decoders/FormatDecoders.{hpp,cpp}: an orphan (bare GLSL strings, called
nowhere) superseded by the GPUVideoDecoder-based factory.
- HostPinnedRing: replace the 4-value HostPinnedFormat enum (a strict subset
duplicate) with the shared VideoPixelFormat; stride now comes from
interop::defaultStride (identical values), toDvpFormat keyed on VideoPixelFormat.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FnqYUYn7AVxBQFZywarDNT
Plan to add DeckLink/Magewell/Bluefish/Deltacast as backends behind a single unified "Direct Video I/O" device that branches on the detected card, with AJA folded in as the reference backend. Covers the shared output-backend extraction, the vendor registry, per-vendor SDK wiring (enum/output/input/GPU-direct tiers/ formats/signal/HDR/ANC), the full options matrix, CMake SDK gating, testing, and phased sequencing. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FnqYUYn7AVxBQFZywarDNT
The output-side counterpart to DMACaptureBackend. A vendor implements it; the (forthcoming) shared DirectVideoOutputNode composes the already-generic pieces around it: makeWireEncoder(wireFormat), selectGpuDirectStrategy(gpuDirect Candidates), HostStagedOutput(planes/registrar/customStage), PacedFramePump( pacingHooks). This is the generalisation of AJANode::createOutput; AJA will be ported onto it next as the reference backend (Phase A of DIRECT_VIDEO_IO_PLAN). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FnqYUYn7AVxBQFZywarDNT
…colorConversion Lets the shared output node stay vendor-neutral: encoderFormat() (differs from wireFormat when a CPU repack bridges them, e.g. v210 non-mod-6 -> UYVY), prefersFloatRender() (RGBA16F intermediate for >8-bit/HDR), colorConversion() (the RGB->wire colour-matrix shader). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FnqYUYn7AVxBQFZywarDNT
The vendor-neutral OutputNode for capture-card playout: owns the QRhi + render loop + createOutput orchestration and drives everything through a DirectVideoOutputBackend (makeWireEncoder(encoderFormat), selectGpuDirect Strategy(gpuDirectCandidates), HostStagedOutput(planes/registrar/customStage), PacedFramePump(pacingHooks)). Backend gains frameRate()/isOpen(); open() drops the (pre-QRhi) rhi arg. Public diagnostics: activeStrategyName(), pacing*(). A vendor output node is now a thin subclass that constructs the node with its backend. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FnqYUYn7AVxBQFZywarDNT
Per design decision: only a handful of vendors, so the unified device hardcodes the compiled-in vendor list behind #if SCORE_HAS_<VENDOR> and dispatches with a plain switch on a vendor tag (no registry / registration indirection). The unified protocol/device/settings + the dispatch live in score-addon-videoio alongside the vendor backends; score-plugin-gfx keeps only the interfaces + nodes. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FnqYUYn7AVxBQFZywarDNT
Add a no-regression, opt-in GPU-direct output download to the shared host- staged path, reusing the existing (until now unconsumed) HostPinnedRing TextureToBuffer + DVP backend instead of reinventing a multi-slot output ring. - GPUVideoEncoder gains two additive, default-preserving virtuals: outputTexture() (nullptr by default) and setReadbackEnabled(bool) (no-op). UYVY/V210/BGRA (single-plane) override them: expose m_outTexture and gate the exec() readback on a flag. Defaults => byte-identical existing behavior. - HostStagedOutputConfig gains preferGpuDownload + caps. When both are set and both encoders expose an output texture, init() builds a HostPinnedRing configured to the ENCODER TEXTURE geometry (RGBA8, texW*4 stride) — so the ring's DVP registration (sysmem + source texture) matches the texture, no HostPinnedRing change needed. Engages only when a GPU-direct backend is selected (not CpuStaging/None) and slot bytes == frameByteSize; then it registers each slot via the vendor registrar, disables the encoder readback (no double transfer), and skips the CPU std::vector ring. Any failure falls back to the unchanged CPU path. prepareNextFrame() DVP-copies the encoder texture into the next ring slot (synchronous) and returns its host pointer. - DirectVideoOutputBackend gains prefersGpuDownload() (default false, AJA unchanged). DirectVideoOutputNode probes GpuCapabilities once and passes it + the opt-in into HostStagedOutputConfig. AJA and the CPU readback path are byte-identical (default-off). Compile-only. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FnqYUYn7AVxBQFZywarDNT
The vendor-neutral NVIDIA-DVP shim templates (Dvp{Capture,Output}{Gl,D3D11} +
the DmaLockPolicy concept/NoDmaLock) were living in the score-addon-videoio
addon, but they're vendor-neutral gfx infrastructure — parameterized by a
DmaLockPolicy and depending only on nv_dvp_bridge + the GpuDirect*Strategy
interfaces, all of which already live here. Relocate them to Graph/interop/
alongside HostPinnedRing/HostStagedOutput and rename the namespace
Gfx::gpudirect -> score::gfx::interop to match the folder. Header-only; gfx
doesn't compile them itself (no consumer yet), it just provides them to the
capture-card addons. No behavior change.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FnqYUYn7AVxBQFZywarDNT
…pers
Seam B from the gpudirect taxonomy: a vendor-neutral allocator of RDMA-capable
GPU VRAM for cards that DMA straight to/from VRAM (e.g. Deltacast
VHD_CreateSlotEx(RDMAEnabled=TRUE)). Counterpart to HostPinnedRing's host-buffer
tier. No consumer yet — this is the foundation a vendor backend will use.
- interop/RdmaGpuBuffer.{hpp,cpp}: allocate N slots, each exposing the per-API
handoff {gpuVA, size, opaque}. Backends:
* Cuda — reuses CudaVmmAllocator (CUdeviceptr, gpuDirectRDMACapable). REAL.
* Vulkan (QT_HAS_VULKAN) — vkinterop::createRdmaBuffer (VkRemoteAddressNV). REAL.
* HostFallback — 64 KiB-aligned host memory (non-RDMA app-buffer path). REAL.
* D3D12 — scaffolded + gated (needs SCORE_HAS_NVAPI + the NvAPI SDK, which
isn't part of the score build); returns unavailable for now.
- vkinterop: createRdmaBuffer / getMemoryRemoteAddress / destroyRdma, built on
VK_NV_external_memory_rdma (RDMA_CAPABLE memory + vkGetMemoryRemoteAddressNV,
via the existing devFuncs/resolveDeviceFn conventions). Compile out to a safe
nullopt when the extension isn't in the Vulkan headers.
Compile-only (no Deltacast/Quadro here). gfx builds clean; videoio still links.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FnqYUYn7AVxBQFZywarDNT
Symmetric inverse of cuda_p2p_copy_buffer_to_array: copies a CUDA array (level 0 of a CUDA-imported VkImage) into a flat device buffer (an RDMA-capable CUDA VMM slot the card DMAs out). The per-frame texture->VRAM copy for GPU-direct OUTPUT, the counterpart to the buffer->texture copy used by capture. Same cuMemcpy2DAsync + stream-sync shape; additive (new function, nothing else changed). First consumer: the Deltacast RDMA output strategy. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FnqYUYn7AVxBQFZywarDNT
CudaVmmAllocator now sets CU_POINTER_ATTRIBUTE_SYNC_MEMOPS on each mapped VMM range (via a newly-loaded cuPointerSetAttribute in the CudaFunctions shim). GPUDirect-RDMA engines like Deltacast's VHD_CreateSlotEx(RDMAEnabled=TRUE) and Rivermax require this attribute to DMA into the buffer; without it the RDMA capture/output path would be rejected at runtime on real hardware. Best-effort (null-checked, non-fatal) — honoured on RDMA-capable GPUs, ignored elsewhere. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FnqYUYn7AVxBQFZywarDNT
…ams) + CUDA binary-semaphore import Replaces the Vulkan InteropFence stub with a working implementation for the GPU-direct RDMA output path (Deltacast), so the CUDA array->buffer copy never reads a half-written VkImage. - CudaP2PBridge: add cuda_p2p_import_vulkan_semaphore_binary(), a sibling of the existing timeline importer that passes CU_EXTERNAL_SEMAPHORE_HANDLE_TYPE_ OPAQUE_WIN32 (/_OPAQUE_FD) to importSemaphore(). cuda_p2p_wait_semaphore already works for binary (value ignored) — waited with value 0. - InteropFence: InteropFenceVulkan holds a ring of 3 exportable BINARY VkSemaphores. signalAfterEncode() asks QRhi to signal m_vkSem[value%3] at its next queue submit via setQueueSubmitParams (consumed by endOffscreenFrame); waitOnCuda() schedules a CUDA-stream wait on the matching imported semaphore. Export fn resolved via QVulkanInstance::getInstanceProcAddr (vkGetSemaphoreWin32HandleKHR / vkGetSemaphoreFdKHR). Any failure -> release() + init returns false so the caller uses its finish() fallback (no partial state). Kept InteropFenceVulkanStub for the no-Vulkan build. The device extensions this needs (VK_KHR_external_semaphore[_win32/_fd]) are already enabled in both QRhi Vulkan device-creation paths (ScreenNode.cpp and VulkanVideoDevice.hpp sharedVulkanDeviceExtensions()). Compile-only (no Quadro/RDMA hardware here); degrades gracefully when the semaphore path is unavailable. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FnqYUYn7AVxBQFZywarDNT
The Vulkan InteropFence had re-rolled vkCreateSemaphore + VkExportSemaphoreCreateInfo + vkGetSemaphoreWin32HandleKHR/FdKHR + CUDA import inline — exactly the boilerplate VkCudaTimelineSemaphore already centralizes. Add a `binary` mode to that helper (default VkSemaphoreCreateInfo is BINARY; imports via the new binary CUDA entry point) and have InteropFenceVulkan hold a ring of them, dropping ~120 duplicated lines. Also fix a latent per-semaphore Win32 HANDLE leak: the exported handle is owned by us (CUDA duplicates it during import), so CloseHandle after import on Win32; on Linux OPAQUE_FD ownership transfers to CUDA. Compile-only; no API change. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FnqYUYn7AVxBQFZywarDNT
…iesce() Two seam-level fixes from the multi-vendor review: - PacedFramePump now parks on a frames-available semaphore BEFORE calling the vendor waitForTick() hook. Guarantees: waitForTick() never fires on an empty ring (a hook that consumes a scarce per-call resource - e.g. DeckLink's free-output-slot permits - can no longer lose it to an idle tick), an always-true waitForTick() no longer busy-spins a core while idle (Deltacast), and a tick timeout re-queues the pending frame. AJA is unaffected: its hook is a pure WaitForOutputVerticalInterrupt, so submits stay VBI-aligned with identical drain-to-newest semantics. - New DirectVideoOutputBackend::quiesce() (default no-op), called by DirectVideoOutputNode::destroyOutput() after the pump stops but before the GPU-direct strategy / host-staged ring are released. Vendors whose submit hands buffers to a retained queue (DeckLink ScheduleVideoFrame, Deltacast RDMA application-buffer slots) stop streaming there so the card never DMA-reads freed memory; synchronous vendors (AJA) keep the no-op and see the exact same teardown order as before. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YTaNKeBdVCyacJ6H2YGPsk
The release() detach guard compared samplers[0].texture against strategy->outputTexture() — true for every strategy, since CPU/DVP strategies report the decoder's own texture. Detaching in that case leaked one QRhiTexture per redock (GPUVideoDecoder::release() is what deletes it). Record at init whether the Vulkan tier-3 texture swap actually happened and gate the detach on that. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YTaNKeBdVCyacJ6H2YGPsk
… 6.9+) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01A8dWKnm8kgkuDaMMjapgFT
TextureShare's factory used #if defined(QT_HAS_VULKAN) but the macro is always defined (0 or 1) by score/gfx/Vulkan.hpp; test its value like the class definition does. Rename RdmaGpuBuffer's local roundUp which collides with CudaVmmAllocator's in the same anonymous namespace under unity builds. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01A8dWKnm8kgkuDaMMjapgFT
Don't build EncoderTester with SCORE_STATIC_PLUGINS: score_init_static_plugins() references every configured addon which the tester doesn't link. Use bridged casts for the ObjC handle pointers in TextureShareMetal under ARC. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01A8dWKnm8kgkuDaMMjapgFT
- PipewireInputDevice: DRM_PRIME frame release used a dangling pw_stream after stop() — the weak_ptr guarded the process-wide context, not the stream. Frames now hold a shared stream token that is nulled on the loop thread before pw_stream_destroy. - PipewireInputDevice: pooled frames recycled across a format renegotiation kept their old geometry, so the next capture copied the new size through the old allocation (heap overflow); reallocate stale frames at pick time. Lock the pool in init_frames(), which runs on the loop thread concurrently with release_frame. - DMACaptureInputNode: implement addOutputPass/removeOutputPass; the renderer holds per-edge passes, so the empty overrides meant a UAF when a downstream render-target spec changed and no pass at all for edges connected after init. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01A8dWKnm8kgkuDaMMjapgFT
- PipewireFormats: RGBA8/BGRA8 mapped to nonexistent fourccs ('RGBA'/
'BGRA' ASCII); use DRM_FORMAT_ABGR8888/ARGB8888 (AB24/AR24, verified
against drm_fourcc.h) so the zero-copy import stops failing.
- PipewireInputDevice: stop() no longer early-returns when
on_node_removed already cleared m_running (leaked the stream +
listener); start() tears down any such leftover stream first.
- PipewireInputDevice: advertise the full planar frame size (NV12 1.5x,
P010 3x, P210 4x) in SPA_PARAM_BUFFERS_size, and validate incoming
chunk sizes against av_image_get_buffer_size before the plane copies.
- PipewireOutputDevice: don't hold the pw thread-loop lock across
render + endOffscreenFrame (multi-ms GPU wait stalling the data
thread); buffers removed while checked out are parked and destroyed
at queue time instead.
- TextureShare (GL): flush QRhi's deferred command list via
beginExternal before creating the producer fence — resourceUpdate
alone doesn't reach the GL stream, so the fence guarded nothing.
- HWCUDA: on partial interop-setup failure, recreate the sampler
textures with their own storage; they could keep wrapping a VkImage
cleanup() had just destroyed.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01A8dWKnm8kgkuDaMMjapgFT
b445d5c to
6e0ed28
Compare
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.