public sealed class GpuOverlay`stat gpu`: where the frame's GPU time went, pass by pass, while you watch.
Remarks
The panel exists so that a cost distribution is noticed rather than measured. Every number here has been available from AppGraphics.GpuFrame since the render graph started emitting a scope per pass, and Samples/13 already prints the same breakdown to its log — but a log line is read by somebody who already suspects something. Three fixes this repository shipped in one week (a 17× screen march, a page-marking pass at 11 % of the frame, a thickness shell that made a hit test meaningless) were each found by reading a breakdown after forming a suspicion. What a log cannot do is show the distribution move as the camera turns.
⚠ Which is why the rows are in the frame's own order and not in cost order. A panel that re-sorts every frame cannot be read while anything is moving: the eye tracks a row's position, and a table whose rows swap places is a table nobody can watch. Cost decides which passes get a row — the most expensive MaxRows of them — and the graph's declaration order decides where each one sits. FrameGraphOverlay makes the identical argument about its colours.
⚠ And why each bar carries a peak that decays rather than a bare instantaneous value. A GPU reading moves by more than ten percent between two frames of a still camera, so an unsmoothed number is unreadable and a smoothed one hides exactly the spike worth seeing. The bar is the smoothed cost and the tick is the worst this pass has been in the last PeakSeconds seconds — so a pass that costs three milliseconds once, while you walk past a wall, leaves a mark that is still there when you look down.
⚠ Two rows exist to stop the panel lying by omission. unattributed is the frame span minus the passes that fill it, which is non-zero when GPU work happens outside any pass the graph ran — a breakdown that does not describe the whole frame. dropped is Dropped, and a non-zero value means the timeline simply stops partway through the frame: the bars that are there look right and the expensive pass somebody opened this for is absent. Neither is a detail; a panel that hid either would make its own incompleteness authoritative.
Here rather than in Vixen.Engine for the reason the assembly exists: GpuFrame is Vixen.Graphics' and IDiagnosticOverlay is Vixen.Engine's, and neither may reference the other. This is the join.
Fields and properties (13)
public const int MaxRowsHow many passes get a row before the rest are folded into one.
public const float PeakSecondsHow long a peak is held before it decays back toward the current cost.
public string NameWhat the console and the toggles call it. Lower case, no spaces.
public OverlayAnchor AnchorWhich corner it is pinned to.
public bool EnabledWhether it is drawn.
public float WidthHow wide the panel is, in pixels.
public GpuFrame FrameThe last frame the GPU finished timing. The host sets this once a frame.
public int LatencyHow many frames back Frame was recorded.
public bool AvailableWhether a profiler is attached at all.
public int DroppedHow many scopes the frame being recorded could not fit. ⚠ Non-zero is a lie by omission.
public int DrawnRowsHow many pass rows the last Draw put on screen.
public float UnattributedFractionThe share of the frame no pass accounted for, from zero to one.
public IReadOnlyList<string> VisiblePassesWhich passes have a row, top to bottom, as of the last Draw.
Methods (3)
public double PeakOf(string? pass)The decaying peak cost of one pass, in milliseconds, or zero if it has no history.
public void Reset()Forgets every smoothed cost and every peak.
public void Draw(OverlaySurface surface, in GameTime time)Draws it.
Used by (2)
- AppGraphicsVixen.App.Hosting
- GpuOverlayTestsVixen.Engine.Renderer.Tests