protected override void Draw(DrawState state) { //store the global colour state.SetShaderGlobal("colour", Color.Red.ToVector4()); //set the on screen text statusText.Text.Clear(); //framerate statusText.Text += (int)state.ApproximateFrameRate; statusText.Text += " fps"; #if DEBUG //display some statistics about the render DrawStatistics stats; state.GetPreviousFrameStatistics(out stats); statusText.Text += ", "; statusText.Text += stats.DefaultCullerTestBoxCount + stats.DefaultCullerTestSphereCount; statusText.Text += " cull tests performed, "; if (state.SupportsHardwareInstancing) { statusText.Text += stats.InstancesDrawn; statusText.Text += stats.InstancesDrawn == 1 ? " instance" : " instances"; statusText.Text += " drawn (hardware instancing)"; } else { statusText.Text += stats.DrawIndexedPrimitiveCallCount; statusText.Text += stats.DrawIndexedPrimitiveCallCount == 1 ? " instance" : " instances"; statusText.Text += " drawn"; } #endif statusText.Text.AppendLine(); statusText.Text += cullButtonText; //draw everything drawToScreen.Draw(state); }
/// <summary> /// Draw the statistics /// </summary> /// <param name="state"></param> public void Draw(DrawState state) { #if DEBUG float fade = 8 - state.TotalTimeSeconds * 0.5f; if (fade > 1) fade = 1; if (fade < 0) fade = 0; if (!enabled) { if (toggleTextDisplay != null && fade > 0) { this.toggleTextDisplay.ColourFloat = new Vector4(1, 1, 1, fade); toggleTextDisplay.Draw(state); AlignElements(state); } return; } if (state.Application.IsHiDefDevice) { if (fillRateQuery == null) { GraphicsDevice device = (GraphicsDevice)state; fillRateQuery = new OcclusionQuery(device); fillRateQuery.Begin(); fillRateQueryActive = true; } if (fillRateQueryActive) { fillRateQuery.End(); fillRateQueryActive = false; } } DrawStatistics stats; state.GetPreviousFrameStatistics(out stats); stats -= previousFrameOverhead; if (graphs == null) { const int width = 210; const int height = 128; const int fontPix = 20; List<Call> calls = new List<Call>(); Func<string, Call, float, Graph> add = delegate(string name, Call call, float good) { calls.Add(call); return new Graph(name, width, height, width - fontPix / 2, fontPix, 0, font, -good); }; Func<string, Call, float, Graph> addHalf = delegate(string name, Call call, float good) { calls.Add(call); return new Graph(name, width / 2, height, width / 2 - fontPix / 2, fontPix, 0, font, -good); }; Func<string, Call, float, Graph> addHalfMin1 = delegate(string name, Call call, float good) { calls.Add(call); return new Graph(name, width / 2, height, width / 2 - fontPix / 2, fontPix, 1, font, -good); }; graphs = new Graph[] { add("Frame Rate (Approx)",delegate(ref DrawStatistics s, DrawState dstate) {return (float)dstate.ApproximateFrameRate;}, -20), #if XBOX360 addHalf("Primitives Drawn",delegate(ref DrawStatistics s, DrawState dstate) {return (float)(s.TrianglesDrawn+s.LinesDrawn+s.PointsDrawn);}, 1000000), addHalf("Pixels Drawn\n(Approx)",delegate(ref DrawStatistics s, DrawState dstate) {return Math.Max(0,pixelsFillled - (float)s.XboxPixelFillBias);}, 20000000), // not accurate #else add("Primitives Drawn",delegate(ref DrawStatistics s, DrawState dstate) {return (float)(s.TrianglesDrawn+s.LinesDrawn+s.PointsDrawn);}, 1000000), addHalf("Pixels Drawn",delegate(ref DrawStatistics s, DrawState dstate) {return Math.Max(0,pixelsFillled);}, 18000000), #endif addHalf("Draw Calls",delegate(ref DrawStatistics s, DrawState dstate) {return (float)(s.DrawIndexedPrimitiveCallCount + s.DrawPrimitivesCallCount);}, 300), addHalf("Garbage Collected",delegate(ref DrawStatistics s, DrawState dstate) { if (garbageTracker.Target == null) { garbageTracker.Target = new object(); return 1; } return 0; },0), addHalf("Allocated Bytes (Managed)",delegate(ref DrawStatistics s, DrawState dstate) { return (int)GC.GetTotalMemory(false); },0), #if XBOX360 addHalfMin1("CPU Usage\n(Primary)",delegate(ref DrawStatistics s, DrawState dstate) {return threads[0].Usage;},-0.5f), addHalfMin1("CPU Usage\n(Task Threads)",delegate(ref DrawStatistics s, DrawState dstate) {return (threads[1].Usage+threads[2].Usage+threads[3].Usage) / 3.0f;},-0.25f), #endif }; this.setGraphCalls = calls.ToArray(); } for (int i = 0; i < graphs.Length; i++) { graphs[i].SetGraphValue(setGraphCalls[i](ref stats, state)); graphs[i].Visible = true; } AlignElements(state); DrawStatistics currentPreDraw; state.GetCurrentFrameStatistics(out currentPreDraw); for (int i = 0; i < graphs.Length; i++) { if (graphs[i].Visible) graphs[i].Draw(state); } DrawStatistics currentPostDraw; state.GetCurrentFrameStatistics(out currentPostDraw); previousFrameOverhead = currentPostDraw - currentPreDraw; if (state.Application.IsHiDefDevice) { if (fillRateQuery.IsComplete) { pixelsFillled = (float)fillRateQuery.PixelCount; fillRateQuery.Begin(); fillRateQueryActive = true; } } else pixelsFillled = -1; #endif }
/// <summary> /// Draw the statistics /// </summary> /// <param name="state"></param> public void Draw(DrawState state) { #if DEBUG float fade = 8 - state.TotalTimeSeconds * 0.5f; if (fade > 1) { fade = 1; } if (fade < 0) { fade = 0; } if (!enabled) { if (toggleTextDisplay != null && fade > 0) { this.toggleTextDisplay.ColourFloat = new Vector4(1, 1, 1, fade); toggleTextDisplay.Draw(state); AlignElements(state); } return; } if (fillRateQuery == null) { GraphicsDevice device = state.BeginGetGraphicsDevice(StateFlag.None); fillRateQuery = new OcclusionQuery(device); state.EndGetGraphicsDevice(); if (fillRateQuery.IsSupported) { fillRateQuery.Begin(); fillRateQueryActive = true; } } if (fillRateQuery.IsSupported) { if (fillRateQueryActive) { fillRateQuery.End(); fillRateQueryActive = false; } } DrawStatistics stats; state.GetPreviousFrameStatistics(out stats); stats -= previousFrameOverhead; if (graphs == null) { const int width = 210; const int height = 128; const int fontPix = 20; List <Call> calls = new List <Call>(); List <bool> visibleList = new List <bool>(); Callback <Graph, string, Call, bool, float> add = delegate(string name, Call call, bool visible, float good) { calls.Add(call); visibleList.Add(visible); return(new Graph(name, width, height, width - fontPix / 2, fontPix, 0, font, -good)); }; Callback <Graph, string, Call, bool, float> addHalf = delegate(string name, Call call, bool visible, float good) { calls.Add(call); visibleList.Add(visible); return(new Graph(name, width / 2, height, width / 2 - fontPix / 2, fontPix, 0, font, -good)); }; Callback <Graph, string, Call, bool, float> addHalfMin1 = delegate(string name, Call call, bool visible, float good) { calls.Add(call); visibleList.Add(visible); return(new Graph(name, width / 2, height, width / 2 - fontPix / 2, fontPix, 1, font, -good)); }; graphs = new Graph[] { add("Frame Rate (Approx)", delegate(ref DrawStatistics s, DrawState dstate) { return((float)dstate.ApproximateFrameRate); }, true, -20), add("Frame Draw Time (Ticks)", delegate(ref DrawStatistics s, DrawState dstate) { return(s.ApproximateDrawTimeTicks); }, false, 1.0f / 20.0f), addHalf("Draw Target Passes", delegate(ref DrawStatistics s, DrawState dstate) { return((float)s.DrawTargetsPassCount); }, false, 10), add("Primitives Drawn", delegate(ref DrawStatistics s, DrawState dstate) { return((float)(s.TrianglesDrawn + s.LinesDrawn + s.PointsDrawn)); }, true, 1000000), #if XBOX360 addHalf("Pixels Drawn\n(Approx)", delegate(ref DrawStatistics s, DrawState dstate) { return(Math.Max(0, pixelsFillled - (float)s.XboxPixelFillBias)); }, true, 20000000), // not accurate #else addHalf("Pixels Drawn", delegate(ref DrawStatistics s, DrawState dstate) { return(Math.Max(0, pixelsFillled)); }, true, 18000000), #endif addHalf("Lines Drawn", delegate(ref DrawStatistics s, DrawState dstate) { return((float)(s.LinesDrawn)); }, false, 1000000), addHalf("Points Drawn", delegate(ref DrawStatistics s, DrawState dstate) { return((float)(s.PointsDrawn)); }, false, 1000000), addHalf("Draw Calls", delegate(ref DrawStatistics s, DrawState dstate) { return((float)(s.DrawIndexedPrimitiveCallCount + s.DrawPrimitivesCallCount)); }, true, 300), addHalf("Draw Calls (Indexed)", delegate(ref DrawStatistics s, DrawState dstate) { return((float)(s.DrawIndexedPrimitiveCallCount)); }, false, 300), addHalf("Instances Drawn", delegate(ref DrawStatistics s, DrawState dstate) { return((float)(s.InstancesDrawn)); }, false, 1000), addHalf("Inst.Batch Size (Avg)", delegate(ref DrawStatistics s, DrawState dstate) { return(Avg(s.InstancesDrawn, s.InstancesDrawBatchCount)); }, false, 1000), addHalf("Set Camera Count", delegate(ref DrawStatistics s, DrawState dstate) { return((float)s.SetCameraCount); }, false, 1000), addHalf("Shader Bind Count", delegate(ref DrawStatistics s, DrawState dstate) { return((float)s.ShaderBindCount); }, false, 1000), addHalf("Shader Constant Bytes", delegate(ref DrawStatistics s, DrawState dstate) { return((float)(s.VertexShaderConstantBytesSetTotalCount + s.PixelShaderConstantBytesSetTotalCount)); }, false, 2000000), addHalf("VS Constant Bytes (Avg)", delegate(ref DrawStatistics s, DrawState dstate) { return(Avg(s.VertexShaderConstantBytesSetTotalCount, s.VertexShaderConstantBytesSetCount)); }, false, 1000), addHalf("PS Constant Bytes (Avg)", delegate(ref DrawStatistics s, DrawState dstate) { return(Avg(s.PixelShaderConstantBytesSetTotalCount, s.PixelShaderConstantBytesSetCount)); }, false, 1000), addHalf("VS Complexity (Avg)", delegate(ref DrawStatistics s, DrawState dstate) { return(Avg(s.VertexShaderApproximateInstructionsTotal, s.VertexShaderBoundWithKnownInstructionsCount)); }, false, 64), addHalf("PS Complexity (Avg)", delegate(ref DrawStatistics s, DrawState dstate) { return(Avg(s.PixelShaderApproximateInstructionsTotal, s.PixelShaderBoundWithKnownInstructionsCount)); }, false, 32), addHalf("VS Preshader Complexity (Avg)", delegate(ref DrawStatistics s, DrawState dstate) { return(Avg(s.VertexShaderApproximatePreshaderInstructionsTotal, s.VertexShaderBoundWithKnownInstructionsCount)); }, false, 512), addHalf("PS Preshader Complexity (Avg)", delegate(ref DrawStatistics s, DrawState dstate) { return(Avg(s.PixelShaderApproximatePreshaderInstructionsTotal, s.PixelShaderBoundWithKnownInstructionsCount)); }, false, 512), addHalf("Dirty Render State Count", delegate(ref DrawStatistics s, DrawState dstate) { return((float)s.DirtyRenderStateCount); }, false, 2), add("Vertex Bytes Copied", delegate(ref DrawStatistics s, DrawState dstate) { return((float)(s.VertexBufferByesCopied + s.DynamicVertexBufferByesCopied)); }, false, 1000000), add("Index Bytes Copied", delegate(ref DrawStatistics s, DrawState dstate) { return((float)(s.IndexBufferByesCopied + s.DynamicIndexBufferByesCopied)); }, false, 1000000), add("Resource Device Bytes (Tracked)", delegate(ref DrawStatistics s, DrawState dstate) { return((float)(Resource.GetAllAllocatedDeviceBytes())); }, false, 100000000), addHalf("Resource Count (Tracked)", delegate(ref DrawStatistics s, DrawState dstate) { return((float)(Resource.GetResourceCount())); }, false, 50), addHalf("Resource Managed Bytes (Tracked)", delegate(ref DrawStatistics s, DrawState dstate) { return((float)(Resource.GetAllAllocatedManagedBytes())); }, false, 100000000), addHalf("Unused Resources (Tracked)", delegate(ref DrawStatistics s, DrawState dstate) { return((float)(Resource.CountResourcesNotUsedByDevice())); }, false, 10), addHalfMin1("Culler Efficiency (Sphere)", delegate(ref DrawStatistics s, DrawState dstate) { return(1 - Avg(s.DefaultCullerTestSphereCulledCount, s.DefaultCullerTestSphereCount)); }, false, 1000), addHalfMin1("Culler Efficiency (Box)", delegate(ref DrawStatistics s, DrawState dstate) { return(1 - Avg(s.DefaultCullerTestBoxCulledCount, s.DefaultCullerTestBoxCount)); }, false, 1000), addHalf("AlphaBlend State Changed", delegate(ref DrawStatistics s, DrawState dstate) { return((float)(s.RenderStateAlphaBlendChangedCount)); }, false, 300), addHalf("AlphaTest State Changed", delegate(ref DrawStatistics s, DrawState dstate) { return((float)(s.RenderStateAlphaTestChangedCount)); }, false, 300), addHalf("StencilTest State Changed", delegate(ref DrawStatistics s, DrawState dstate) { return((float)(s.RenderStateStencilTestChangedCount)); }, false, 300), addHalf("Depth/FrustumCull State Changed", delegate(ref DrawStatistics s, DrawState dstate) { return((float)(s.RenderStateDepthColourCullChangedCount)); }, false, 300), addHalf("Tex Sampler Address Changed", delegate(ref DrawStatistics s, DrawState dstate) { return((float)(s.TextureSamplerAddressStateChanged)); }, false, 200), addHalf("Tex Sampler Filter Changed", delegate(ref DrawStatistics s, DrawState dstate) { return((float)(s.TextureSamplerFilterStateChanged)); }, false, 200), addHalf("Texture Changed", delegate(ref DrawStatistics s, DrawState dstate) { return((float)(s.TextureUnitTextureChanged)); }, false, 100), addHalf("Vertex Texture Changed", delegate(ref DrawStatistics s, DrawState dstate) { return((float)(s.VertexTextureUnitTextureChanged)); }, false, 50), add("Bound Textures (Avg)", delegate(ref DrawStatistics s, DrawState dstate) { return(Avg(s.BoundTextureCount, s.BoundTextureCountTotalSamples)); }, false, 4), addHalf("Vertex Textures (Avg)", delegate(ref DrawStatistics s, DrawState dstate) { return(Avg(s.BoundVertexTextureCount, s.BoundTextureCountTotalSamples)); }, false, 1), addHalf("Garbage Collected", delegate(ref DrawStatistics s, DrawState dstate) { if (garbageTracker.Target == null) { garbageTracker.Target = new object(); return(1); } return(0); }, true, 0), #if XBOX360 addHalfMin1("CPU Usage\n(Primary)", delegate(ref DrawStatistics s, DrawState dstate) { return(threads[0].Usage); }, true, -0.5f), addHalfMin1("CPU Usage\n(Task Threads)", delegate(ref DrawStatistics s, DrawState dstate) { return((threads[1].Usage + threads[2].Usage + threads[3].Usage) / 3.0f); }, true, -0.25f), #endif }; this.graphVisible = visibleList.ToArray(); this.setGraphCalls = calls.ToArray(); } for (int i = 0; i < graphs.Length; i++) { if (graphVisible[i] || this.displayAll) { graphs[i].SetGraphValue(setGraphCalls[i](ref stats, state)); graphs[i].Visible = true; } else { graphs[i].Visible = false; } } AlignElements(state); DrawStatistics currentPreDraw; state.GetCurrentFrameStatistics(out currentPreDraw); for (int i = 0; i < graphs.Length; i++) { if (graphs[i].Visible) { graphs[i].Draw(state); } } DrawStatistics currentPostDraw; state.GetCurrentFrameStatistics(out currentPostDraw); previousFrameOverhead = currentPostDraw - currentPreDraw; if (fillRateQuery.IsSupported) { if (fillRateQuery.IsComplete) { pixelsFillled = (float)fillRateQuery.PixelCount; fillRateQuery.Begin(); fillRateQueryActive = true; } } else { pixelsFillled = -1; } #endif }