Skip to content

Commit f2f7037

Browse files
test(audience-sample): hide log pane on Linux PlayMode to skip llvmpipe rasterisation
PR 765 captured a player profile that showed the Unity 6 Linux cells spending roughly 4.5 seconds per frame in Gfx.PresentFrame self time on the render thread. Camera.Render was 2 ms and UI.RenderOverlays 1.45 ms per frame; the 4.5 sec is llvmpipe walking the deferred command buffer and rasterising approximately 2920 batches and 7520 triangles per frame, almost all of which are UI Toolkit log rows generated by the SampleApp's accumulating log pane. LinuxLogPaneSuppression registers a SceneManager.sceneLoaded handler that sets the log ScrollView to display:none after each scene load. display:none skips layout and render but keeps elements in the visual tree, so HasLogEntry (which walks contentContainer.Children() and inspects userData by reference) still observes log rows correctly. Engages only on StandaloneLinux64 builds via #if UNITY_STANDALONE_LINUX. Mac and Windows PlayMode runs are unaffected.
1 parent 5c1040c commit f2f7037

2 files changed

Lines changed: 79 additions & 0 deletions

File tree

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
#nullable enable
2+
3+
#if UNITY_STANDALONE_LINUX
4+
using NUnit.Framework;
5+
using UnityEngine;
6+
using UnityEngine.SceneManagement;
7+
using UnityEngine.UIElements;
8+
9+
namespace Immutable.Audience.Samples.SampleApp.Tests
10+
{
11+
// Linux PlayMode test optimisation: hide the SampleApp log pane so UI
12+
// Toolkit does not generate triangles for its rows during test runs.
13+
//
14+
// The player profile captured on PR 765 showed Render Thread spending
15+
// roughly 4.5 seconds per frame in Gfx.PresentFrame self time on Unity
16+
// 6 Linux cells, with ~2920 batches and ~7520 triangles per frame.
17+
// Camera.Render is 2 ms, UI.RenderOverlays 1.45 ms; the rest is
18+
// llvmpipe rasterising the deferred command buffer at present time.
19+
// The bulk of those triangles come from the log pane, which
20+
// accumulates one row per logged event over the course of a session.
21+
//
22+
// display:none keeps elements in the visual tree (so VisualElement.Q
23+
// and contentContainer.Children() still find them) but skips layout
24+
// and render entirely. Tests assert on log entries via userData on
25+
// each row, which is reference-based, not layout-based, so the
26+
// assertions stay correct.
27+
//
28+
// Engages only on StandaloneLinux64 builds (gated by the #if). Mac
29+
// and Windows PlayMode runs are unaffected.
30+
[SetUpFixture]
31+
public sealed class LinuxLogPaneSuppression
32+
{
33+
[OneTimeSetUp]
34+
public void RegisterSceneHook()
35+
{
36+
SceneManager.sceneLoaded += HideLogPane;
37+
}
38+
39+
[OneTimeTearDown]
40+
public void DeregisterSceneHook()
41+
{
42+
SceneManager.sceneLoaded -= HideLogPane;
43+
}
44+
45+
// Re-fires for every scene load. The SampleApp's UIDocument runs
46+
// its UI initialisation in Awake, so by the time sceneLoaded
47+
// fires the log ScrollView is in the tree and ready to be
48+
// styled. The hook is idempotent across loads.
49+
private static void HideLogPane(Scene scene, LoadSceneMode mode)
50+
{
51+
var sample = Object.FindFirstObjectByType<AudienceSample>(FindObjectsInactive.Include);
52+
if (sample == null) return;
53+
54+
var doc = sample.GetComponent<UIDocument>();
55+
if (doc == null) return;
56+
57+
var root = doc.rootVisualElement;
58+
if (root == null) return;
59+
60+
var log = root.Q<ScrollView>(SampleAppUi.LogScrollView);
61+
if (log == null) return;
62+
63+
log.style.display = new StyleEnum<DisplayStyle>(DisplayStyle.None);
64+
Debug.Log("[LinuxLogPaneSuppression] log pane hidden for Linux PlayMode test run.");
65+
}
66+
}
67+
}
68+
#endif

examples/audience/Assets/SampleApp/Tests/Runtime/LinuxLogPaneSuppression.cs.meta

Lines changed: 11 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)