public override void Render(DirectXCanvas canvas, ThreadScroll scroll, DirectXCanvas.Layer layer) { if (layer == DirectXCanvas.Layer.Background) { SharpDX.Matrix world = SharpDX.Matrix.Scaling((float)scroll.Zoom, 1.0f, 1.0f); world.TranslationVector = new SharpDX.Vector3(-(float)(scroll.ViewUnit.Left * scroll.Zoom), 0.0f, 0.0f); BackgroundMeshLines.World = world; BackgroundMeshTris.World = world; canvas.Draw(BackgroundMeshTris); canvas.Draw(BackgroundMeshLines); Data.Utils.ForEachInsideInterval(Group.MainThread.Events, scroll.ViewTime, frame => { Interval interval = scroll.TimeToPixel(frame.Header); String text = String.Format(System.Globalization.CultureInfo.InvariantCulture, "{0:0.0} ms", frame.Header.Duration); // 2 times to emulate "bold" for (int i = 0; i < 2; ++i) { canvas.Text.Draw(new Point(interval.Left, Offset), text, TextColor, TextAlignment.Center, interval.Width); } }); } }
public override void OnMouseMove(Point point, ThreadScroll scroll) { ITick tick = scroll.PixelToTime(point.X); int index = Data.Utils.BinarySearchClosestIndex(Timestamps, tick.Start); if (0 <= index && index + 1 < Timestamps.Count) { double leftPx = scroll.TimeToPixel(Timestamps[index]); double rightPx = scroll.TimeToPixel(Timestamps[index + 1]); Rect rect = new Rect(leftPx, Offset + RenderParams.BaseMargin, rightPx - leftPx, Height - RenderParams.BaseMargin); List <double> values = new List <double>(); for (int entryIndex = 0; entryIndex < Entries.Count; ++entryIndex) { values.Add(Entries[entryIndex].Values[index]); } StringBuilder builder = new StringBuilder(); builder.AppendFormat("NumCores [{0}]: ", values.Sum()); for (int i = 0; i < values.Count; ++i) { if (i != 0) { builder.Append("+"); } builder.Append(values[i]); //builder.AppendFormat("{0}({1})", values[i], entries[i].Name); } ChartHover?.Invoke(point, rect, builder.ToString()); } else { ChartHover?.Invoke(point, new Rect(), null); } }
void DrawSelection(DirectX.DirectXCanvas canvas) { foreach (Selection selection in SelectionList) { if (selection.Frame != null) { ThreadRow row = id2row[selection.Frame.Header.ThreadIndex]; Durable intervalTime = selection.Node == null ? (Durable)selection.Frame.Header : (Durable)selection.Node.Entry; Interval intervalPx = scroll.TimeToPixel(intervalTime); Rect rect = new Rect(intervalPx.Left, row.Offset + 2.0 * RenderParams.BaseMargin, intervalPx.Width, row.Height - 4.0 * RenderParams.BaseMargin); for (int i = 0; i < SelectionBorderCount; ++i) { rect.Inflate(SelectionBorderStep, SelectionBorderStep); SelectionMesh.AddRect(rect, FrameSelection.Color); } } } SelectionMesh.Update(canvas.RenderDevice); canvas.Draw(SelectionMesh); }
public override void OnMouseMove(Point point, ThreadScroll scroll) { EventNode node = null; EventFrame frame = null; int level = FindNode(point, scroll, out frame, out node); if (level != -1) { Interval interval = scroll.TimeToPixel(node.Entry); Rect rect = new Rect(interval.Left, Offset + level * RenderParams.BaseHeight + RenderParams.BaseMargin, interval.Width, RenderParams.BaseHeight - RenderParams.BaseMargin); EventNodeHover?.Invoke(point, rect, this, node); } else { EventNodeHover?.Invoke(point, new Rect(), this, null); } }
public override void Render(DirectXCanvas canvas, ThreadScroll scroll, DirectXCanvas.Layer layer, Rect box) { if (layer == DirectXCanvas.Layer.Foreground) { Matrix world = GetWorldMatrix(scroll, false); //Matrix world = new Matrix(scroll.Zoom, 0.0, 0.0, 1.0, -scroll.ViewUnit.Left * scroll.Zoom, 0.0); if (BackgroundMeshTris != null) { BackgroundMeshTris.WorldTransform = world; canvas.Draw(BackgroundMeshTris); } if (BackgroundMeshLines != null) { BackgroundMeshLines.WorldTransform = world; canvas.Draw(BackgroundMeshLines); } double yOffset = Offset + (Height - RenderParams.BaseHeight) * 0.5; if (Group.MainThread != null) { Data.Utils.ForEachInsideInterval(Group.MainThread.Events, scroll.ViewTime, (frame, index) => { Interval interval = scroll.TimeToPixel(frame.Header); uint?frameNumber = FrameGroup.GetFrameNumber(frame); String text = String.Format(System.Globalization.CultureInfo.InvariantCulture, "Frame {0} ({1:0.0}ms)", frameNumber.HasValue ? frameNumber.Value : (uint)index, frame.Header.Duration); // 2 times to emulate "bold" for (int i = 0; i < 2; ++i) { canvas.Text.Draw(new Point(interval.Left, yOffset), text, TextColor, TextAlignment.Center, interval.Width); } }); } } }
public override void OnMouseHover(Point point, ThreadScroll scroll, List <object> dataContext) { EventNode node = null; EventFrame frame = null; ITick tick = scroll.PixelToTime(point.X); if (FindNode(point, scroll, out frame, out node) != -1) { dataContext.Add(node); } // show current sync info if (EventData.Sync != null && EventData.Sync != null) { int index = Data.Utils.BinarySearchClosestIndex(EventData.Sync, tick.Start); if (index != -1) { bool insideWaitInterval = false; WaitInterval interval = new WaitInterval() { Start = EventData.Sync[index].Finish, Reason = EventData.Sync[index].Reason }; if (index + 1 < EventData.Sync.Count) { if (EventData.Sync[index].Finish < tick.Start && tick.Start < EventData.Sync[index + 1].Start) { UInt64 threadId = EventData.Sync[index].NewThreadId; ThreadDescription threadDesc = null; Group.Board.ThreadDescriptions.TryGetValue(threadId, out threadDesc); interval.newThreadDesc = threadDesc; interval.newThreadId = threadId; interval.Finish = EventData.Sync[index + 1].Start; dataContext.Add(interval); insideWaitInterval = true; } } if (!insideWaitInterval) { interval.Reason = SyncReason.SyncReasonActive; interval.Start = EventData.Sync[index].Start; interval.Finish = EventData.Sync[index].Finish; interval.core = (byte)EventData.Sync[index].Core; dataContext.Add(interval); } } } if (node != null) { // build all intervals inside selected node int from = Data.Utils.BinarySearchClosestIndex(frame.Synchronization, node.Entry.Start); int to = Data.Utils.BinarySearchClosestIndex(frame.Synchronization, node.Entry.Finish); if (from >= 0 && to >= from) { IntPair[] waitInfo = new IntPair[(int)SyncReason.SyncReasonCount]; for (int index = from; index <= to; ++index) { SyncReason reason = frame.Synchronization[index].Reason; int reasonIndex = (int)reason; long idleStart = frame.Synchronization[index].Finish; long idleFinish = (index + 1 < frame.Synchronization.Count) ? frame.Synchronization[index + 1].Start : frame.Finish; if (idleStart > node.Entry.Finish) { continue; } long idleStartClamped = Math.Max(idleStart, node.Entry.Start); long idleFinishClamped = Math.Min(idleFinish, node.Entry.Finish); long durationInTicks = idleFinishClamped - idleStartClamped; waitInfo[reasonIndex].duration += durationInTicks; waitInfo[reasonIndex].count++; } NodeWaitIntervalList intervals = new NodeWaitIntervalList(); for (int i = 0; i < waitInfo.Length; i++) { if (waitInfo[i].count > 0) { NodeWaitInterval interval = new NodeWaitInterval() { Start = 0, Finish = waitInfo[i].duration, Reason = (SyncReason)i, NodeInterval = node.Entry, Count = waitInfo[i].count }; intervals.Add(interval); } } intervals.Sort((a, b) => { return(Comparer <long> .Default.Compare(b.Finish, a.Finish)); }); if (intervals.Count > 0) { dataContext.Add(intervals); } } } // FindNode if (EventData.Callstacks != null && scroll.DrawCallstacks != 0) { int startIndex = Data.Utils.BinarySearchClosestIndex(EventData.Callstacks, tick.Start); for (int i = startIndex; (i <= startIndex + 1) && (i < EventData.Callstacks.Count) && (i != -1); ++i) { double pixelPos = scroll.TimeToPixel(EventData.Callstacks[i]); if (Math.Abs(pixelPos - point.X) < CallstackMarkerRadius * 1.2 && (EventData.Callstacks[i].Reason & scroll.DrawCallstacks) != 0) { dataContext.Add(EventData.Callstacks[i]); break; } } } }
public override void Render(DirectX.DirectXCanvas canvas, ThreadScroll scroll, DirectXCanvas.Layer layer, Rect box) { if (!IsVisible) { return; } Matrix world = GetWorldMatrix(scroll); if (layer == DirectXCanvas.Layer.Background) { Draw(canvas, Blocks, world); if (FilterMesh != null) { FilterMesh.WorldTransform = world; canvas.Draw(FilterMesh); } if (scroll.SyncDraw == ThreadScroll.SyncDrawType.Wait) { Draw(canvas, SyncMesh, world); } if (SyncWorkMesh != null && scroll.SyncDraw == ThreadScroll.SyncDrawType.Work) { Draw(canvas, SyncWorkMesh, world); } Data.Utils.ForEachInsideInterval(EventData.Events, scroll.ViewTime, frame => { GetTree(frame).ForEachChild((node, level) => { Entry entry = (node as EventNode).Entry; Interval intervalPx = scroll.TimeToPixel(entry); if (intervalPx.Width < TextDrawThreshold || intervalPx.Right < 0.0 || level >= MaxDepth) { return(false); } if (intervalPx.Left < 0.0) { intervalPx.Width += intervalPx.Left; intervalPx.Left = 0.0; } double lum = DirectX.Utils.GetLuminance(entry.Description.ForceColor); Color color = lum < DirectX.Utils.LuminanceThreshold ? Colors.White : Colors.Black; canvas.Text.Draw(new Point(intervalPx.Left + TextDrawOffset, Offset + level * RenderParams.BaseHeight), entry.Description.Name, color, TextAlignment.Left, intervalPx.Width - TextDrawOffset); return(true); }); }); } if (layer == DirectXCanvas.Layer.Foreground) { if (CallstackMeshPolys != null && CallstackMeshLines != null && scroll.DrawCallstacks != 0) { double width = CallstackMarkerRadius; double height = CallstackMarkerRadius; double offset = Offset + RenderParams.BaseHeight * 0.5; Data.Utils.ForEachInsideInterval(EventData.Callstacks, scroll.ViewTime, callstack => { if ((callstack.Reason & scroll.DrawCallstacks) != 0) { double center = scroll.TimeToPixel(callstack); Point[] points = new Point[] { new Point(center - width, offset), new Point(center, offset - height), new Point(center + width, offset), new Point(center, offset + height) }; Color fillColor = (callstack.Reason == CallStackReason.AutoSample) ? CallstackColor : SystemCallstackColor; Color strokeColor = Colors.Black; CallstackMeshPolys.AddRect(points, fillColor); CallstackMeshLines.AddRect(points, strokeColor); } }); CallstackMeshPolys.Update(canvas.RenderDevice); CallstackMeshLines.Update(canvas.RenderDevice); //CallstackMeshPolys.World = world; //CallstackMeshLines.World = world; canvas.Draw(CallstackMeshPolys); canvas.Draw(CallstackMeshLines); } } }
public override void Render(DirectX.DirectXCanvas canvas, ThreadScroll scroll, DirectXCanvas.Layer layer) { SharpDX.Matrix world = SharpDX.Matrix.Scaling((float)scroll.Zoom, (float)((Height - 2.0 * RenderParams.BaseMargin) / scroll.Height), 1.0f); world.TranslationVector = new SharpDX.Vector3(-(float)(scroll.ViewUnit.Left * scroll.Zoom), (float)((Offset + 1.0 * RenderParams.BaseMargin) / scroll.Height), 0.0f); if (layer == DirectXCanvas.Layer.Background) { if (Mesh != null) { Mesh.World = world; canvas.Draw(Mesh); } if (FilterMesh != null) { FilterMesh.World = world; canvas.Draw(FilterMesh); } if (SyncMesh != null && scroll.SyncDraw == ThreadScroll.SyncDrawType.Wait) { SyncMesh.World = world; canvas.Draw(SyncMesh); } if (SyncWorkMesh != null && scroll.SyncDraw == ThreadScroll.SyncDrawType.Work) { SyncWorkMesh.World = world; canvas.Draw(SyncWorkMesh); } Data.Utils.ForEachInsideInterval(EventData.Events, scroll.ViewTime, frame => { frame.CategoriesTree.ForEachChild((node, level) => { Entry entry = (node as EventNode).Entry; Interval intervalPx = scroll.TimeToPixel(entry); if (intervalPx.Width < TextDrawThreshold || intervalPx.Right < 0.0) { return(false); } if (intervalPx.Left < 0.0) { intervalPx.Width += intervalPx.Left; intervalPx.Left = 0.0; } double lum = DirectX.Utils.GetLuminance(entry.Description.Color); Color color = lum < 0.33 ? Colors.White : Colors.Black; canvas.Text.Draw(new Point(intervalPx.Left + TextDrawOffset, Offset + level * RenderParams.BaseHeight), entry.Description.Name, color, TextAlignment.Left, intervalPx.Width - TextDrawOffset); return(true); }); }); } if (layer == DirectXCanvas.Layer.Foreground) { if (CallstackMeshPolys != null && CallstackMeshLines != null && scroll.DrawCallstacks) { double width = CallstackMarkerSize * 0.5; double height = (CallstackMarkerSize / RenderParams.BaseHeight) / MaxDepth; double offset = (CallstackMarkerOffset / RenderParams.BaseHeight) / MaxDepth; Data.Utils.ForEachInsideInterval(EventData.Callstacks, scroll.ViewTime, callstack => { double center = scroll.TimeToPixel(callstack); Point a = new Point(center - width, offset); Point b = new Point(center, offset + height); Point c = new Point(center + width, offset); CallstackMeshPolys.AddTri(a, b, c, (callstack.Reason == CallStackReason.AutoSample) ? CallstackColor : SystemCallstackColor); CallstackMeshLines.AddTri(a, b, c, Colors.Black); }); CallstackMeshPolys.Update(canvas.RenderDevice); CallstackMeshLines.Update(canvas.RenderDevice); CallstackMeshPolys.World = world; CallstackMeshLines.World = world; canvas.Draw(CallstackMeshPolys); canvas.Draw(CallstackMeshLines); } } }