Skip to content

Improve Linux/Mesa support#12

Open
jonpepler wants to merge 1 commit into
jrodrigv:mainfrom
jonpepler:main
Open

Improve Linux/Mesa support#12
jonpepler wants to merge 1 commit into
jrodrigv:mainfrom
jonpepler:main

Conversation

@jonpepler
Copy link
Copy Markdown

⚠️ I've made heavy use of AI for this. The changes work for my purposes so I'm offering them back, but I can't test on other platforms.

Fix Hullcam frame capture on Linux / Mesa (all-white JPEGs)

Hullcam frames arrive as all-white JPEGs on native Linux installs (tested: Steam Deck SteamOS 3.x, native KSP 1.12.5 Linux). Metadata (camera name, speed, altitude) flows correctly; only the rendered pixels are broken.

Three bugs in TrackingCamera.SendCameraImage() compound on Linux where they happen to be masked on Windows/D3D:

  1. Graphics.CopyTexture(RT, Tex2D) followed by AsyncGPUReadback.Request(Tex2D, 0) relies on the driver implicitly synchronising the GPU→GPU copy before the readback. Mesa's OpenGL driver doesn't guarantee that ordering; readback returns without error but the destination Texture2D contains uninitialised pixels - which read back as pure white in ARGB32.
  2. Task.Run + ContinueWith running LoadRawTextureData and EncodeToJPG off the main thread. Unity's texture APIs are main-thread-only per Unity's docs. D3D tolerates it; Mesa doesn't.
  3. Capturing request.GetData<byte>() into a Task closure. The returned NativeArray<byte> is only valid inside the readback callback's synchronous scope; once it returns the backing allocation is disposed. The .ContinueWith thread-pool task reads freed memory.

Diagnostic evidence

A debug build logging AsyncGPUReadback.Request(TargetCamRenderTexture, 0, …) directly (skipping the Graphics.CopyTexture intermediate) showed 100% of readbacks returning hasError=true on Mesa. The upstream copy-to-Tex2D-first path sidesteps that specific error but loses the pixel data a different way, hence all-white frames rather than no frames at all.

Fix

Replace the async dance with the canonical synchronous capture pattern:

var previousActive = RenderTexture.active;
RenderTexture.active = TargetCamRenderTexture;
_texture2D.ReadPixels(new Rect(0, 0, _texture2D.width, _texture2D.height), 0, 0);
_texture2D.Apply();
RenderTexture.active = previousActive;
_jpgTexture = _texture2D.EncodeToJPG();
// Only the gRPC send goes off-thread: pure I/O, no Unity APIs.
Task.Run(() => GrpcClient.SendCameraTextureAsync(payload));

Synchronous ReadPixels blocks the main thread for ~1–2 ms per Hullcam frame at 768x768.

Compatibility

Strictly better-behaved on all platforms, not Linux-specific. Windows/D3D users see identical results with no regression.

Testing

  • Native Linux (Steam Deck, SteamOS 3): confirmed working live video feeds
  • No Windows install available for regression testing; happy to coordinate with someone who has one

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant