Skip to content

D3D12Renderer m_composeTargets: show-thread emplace_back/resize races editor readers #75

Description

@duremovich

From the 2026-07-03 comprehensive review.

The show thread grows/mutates m_composeTargets at runtime while the editor thread indexes it — no lock, no reserve. Show-thread writes: createComposeTarget does emplace_back (D3D12Renderer.cpp:3525 — realloc moves every element); resizeComposeTarget recreates sub-resources + rewrites srvHandles (:3646+). Reached from CompositorSystem::update (show thread) whenever a screen is added or a layer gains its first effect mid-show. Editor-thread reads: getComposeTargetTextureID (:3790), isComposeTargetReady (:3836), getComposeTargetStableSrvSlot (:3807) from StageWindow.cpp:149-155 and ProjectorCalibrationWindow.cpp:440,680.

Triple-buffering (ADR-0014 §2) guards RT contents, not vector structure. The comment at D3D12Renderer.hpp:718-719 ("targets only added at startup before the show thread runs") is false.

Failure: add a screen / toggle a first effect during a live show with Stage or Calibration window open → torn D3D12_GPU_DESCRIPTOR_HANDLE → ImGui binds a garbage descriptor → GPU page fault / DXGI_ERROR_DEVICE_REMOVED.

Fix: reserve(MAX_COMPOSE_TARGETS) at init + atomic ready gate; the resize resource-swap path additionally needs a mutex or generation gate (reserve alone kills the realloc UAF but not the resize race).

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingtier:coreLives in core (GPLv3, in-repo); always free, fully featured

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions