Browse Source

Added top-level profiling blocks for frame execution. Explicitly call Profiler::BeginFrame() and EndFrame() in Time subsystem to not depend on event subscription order. Profiler max. display depth in DebugHud can be specified.

Lasse Öörni 13 years ago
parent
commit
9ab2bf4c14

+ 11 - 19
Engine/Core/Profiler.cpp

@@ -45,9 +45,6 @@ Profiler::Profiler(Context* context) :
 {
     root_ = new ProfilerBlock(0, "Root");
     current_ = root_;
-    
-    SubscribeToEvent(E_BEGINFRAME, HANDLER(Profiler, HandleBeginFrame));
-    SubscribeToEvent(E_ENDFRAME, HANDLER(Profiler, HandleEndFrame));
 }
 
 Profiler::~Profiler()
@@ -84,7 +81,7 @@ void Profiler::ClearAccumulated()
     accumulatedFrames_ = 0;
 }
 
-String Profiler::GetData(bool showUnused, bool showAccumulated, bool showTotal) const
+String Profiler::GetData(bool showUnused, bool showAccumulated, bool showTotal, unsigned maxDepth) const
 {
     String output;
     
@@ -96,12 +93,15 @@ String Profiler::GetData(bool showUnused, bool showAccumulated, bool showTotal)
         output += String("                                    Count     Average       Total      Count     Average       Total\n\n");
     }
     
-    GetData(root_, output, 0, showUnused, showAccumulated, showTotal);
+    if (!maxDepth)
+        maxDepth = 1;
+
+    GetData(root_, output, 0, maxDepth, showUnused, showAccumulated, showTotal);
     
     return output;
 }
 
-void Profiler::GetData(ProfilerBlock* block, String& output, unsigned indent, bool showUnused, bool showAccumulated, bool showTotal) const
+void Profiler::GetData(ProfilerBlock* block, String& output, unsigned depth, unsigned maxDepth, bool showUnused, bool showAccumulated, bool showTotal) const
 {
     char line[LINE_MAX_LENGTH];
     char indentedName[LINE_MAX_LENGTH];
@@ -109,6 +109,9 @@ void Profiler::GetData(ProfilerBlock* block, String& output, unsigned indent, bo
     unsigned frames = Max(totalFrames_, 1);
     unsigned accumulatedFrames = Max(accumulatedFrames_, 1);
     
+    if (depth > maxDepth)
+        return;
+
     // Do not print the root block as it does not collect any actual data
     if (block != root_)
     {
@@ -134,7 +137,7 @@ void Profiler::GetData(ProfilerBlock* block, String& output, unsigned indent, bo
         if (showUnused || frameCount || (showAccumulated && accumulatedCount))
         {
             memset(indentedName, ' ', NAME_MAX_LENGTH);
-            indentedName[indent] = 0;
+            indentedName[depth] = 0;
             strcat(indentedName, block->GetName());
             indentedName[strlen(indentedName)] = ' ';
             indentedName[NAME_MAX_LENGTH] = 0;
@@ -164,22 +167,11 @@ void Profiler::GetData(ProfilerBlock* block, String& output, unsigned indent, bo
                     totalCount, avgTotalTime, totalTime);
             }
             output += String(line);
-            
-            indent++;
         }
     }
     
     const PODVector<ProfilerBlock*>& children = block->GetChildren();
     for (PODVector<ProfilerBlock*>::ConstIterator i = children.Begin(); i != children.End(); ++i)
-        GetData(*i, output, indent, showUnused, showAccumulated, showTotal);
-}
-
-void Profiler::HandleBeginFrame(StringHash eventType, VariantMap& eventData)
-{
-    BeginFrame();
+        GetData(*i, output, depth + 1, maxDepth, showUnused, showAccumulated, showTotal);
 }
 
-void Profiler::HandleEndFrame(StringHash eventType, VariantMap& eventData)
-{
-    EndFrame();
-}

+ 3 - 7
Engine/Core/Profiler.h

@@ -208,18 +208,14 @@ public:
     void ClearAccumulated();
     
     /// Return profiling data as text output.
-    String GetData(bool showUnused = false, bool showAccumulated = false, bool showTotal = false) const;
+    String GetData(bool showUnused = false, bool showAccumulated = false, bool showTotal = false, unsigned maxDepth = M_MAX_UNSIGNED) const;
     /// Return the current profiling block.
     const ProfilerBlock* GetCurrentBlock() { return current_; }
     
 private:
     /// Return profiling data as text output for a specified profiling block.
-    void GetData(ProfilerBlock* block, String& output, unsigned indent, bool showUnused, bool showAccumulated, bool showTotal) const;
-    /// Handle begin frame event.
-    void HandleBeginFrame(StringHash eventType, VariantMap& eventData);
-    /// Handle end frame event.
-    void HandleEndFrame(StringHash eventType, VariantMap& eventData);
-    
+    void GetData(ProfilerBlock* block, String& output, unsigned depth, unsigned maxDepth, bool showUnused, bool showAccumulated, bool showTotal) const;
+
     /// Current profiling block.
     ProfilerBlock* current_;
     /// Root profiling block.

+ 25 - 8
Engine/Core/Timer.cpp

@@ -23,6 +23,7 @@
 
 #include "Precompiled.h"
 #include "CoreEvents.h"
+#include "Profiler.h"
 #include "Timer.h"
 
 #ifdef WIN32
@@ -72,19 +73,35 @@ void Time::BeginFrame(float timeStep)
     
     timeStep_ = timeStep;
     
-    // Frame begin event
-    using namespace BeginFrame;
+    Profiler* profiler = GetSubsystem<Profiler>();
+    if (profiler)
+        profiler->BeginFrame();
+
+    {
+        PROFILE(BeginFrame);
+
+        // Frame begin event
+        using namespace BeginFrame;
     
-    VariantMap eventData;
-    eventData[P_FRAMENUMBER] = frameNumber_;
-    eventData[P_TIMESTEP] = timeStep_;
-    SendEvent(E_BEGINFRAME, eventData);
+        VariantMap eventData;
+        eventData[P_FRAMENUMBER] = frameNumber_;
+        eventData[P_TIMESTEP] = timeStep_;
+        SendEvent(E_BEGINFRAME, eventData);
+    }
 }
 
 void Time::EndFrame()
 {
-    // Frame end event
-    SendEvent(E_ENDFRAME);
+    {
+        PROFILE(EndFrame);
+
+        // Frame end event
+        SendEvent(E_ENDFRAME);
+    }
+
+    Profiler* profiler = GetSubsystem<Profiler>();
+    if (profiler)
+        profiler->EndFrame();
 }
 
 void Time::SetTimerPeriod(unsigned mSec)

+ 13 - 15
Engine/Engine/DebugHud.cpp

@@ -58,8 +58,8 @@ OBJECTTYPESTATIC(DebugHud);
 
 DebugHud::DebugHud(Context* context) :
     Object(context),
+    profilerMaxDepth_(M_MAX_UNSIGNED),
     profilerInterval_(1.0f),
-    profilerTimer_(0.0f),
     useRendererStats_(false)
 {
     UI* ui = GetSubsystem<UI>();
@@ -98,7 +98,7 @@ DebugHud::~DebugHud()
     }
 }
 
-void DebugHud::Update(float timeStep)
+void DebugHud::Update()
 {
     Graphics* graphics = GetSubsystem<Graphics>();
     Renderer* renderer = GetSubsystem<Renderer>();
@@ -135,9 +135,7 @@ void DebugHud::Update(float timeStep)
         String mode;
         
         mode += renderModeTexts[renderer->GetRenderMode()];
-        
         mode += " Tex: " + qualityTexts[renderer->GetTextureQuality()];
-        
         mode += " Mat: " + qualityTexts[renderer->GetMaterialQuality()];
         
         mode += " Spec:";
@@ -153,7 +151,6 @@ void DebugHud::Update(float timeStep)
             mode += "Off";
         
         mode += " Size:" + String(renderer->GetShadowMapSize());
-        
         mode += " Quality:" + shadowQualityTexts[renderer->GetShadowQuality()];
         
         mode += " Occlusion:";
@@ -184,16 +181,16 @@ void DebugHud::Update(float timeStep)
     Profiler* profiler = GetSubsystem<Profiler>();
     if (profiler)
     {
-        profilerTimer_ += timeStep;
-        if (profilerTimer_ >= profilerInterval_)
+        if (profilerTimer_.GetMSec(false) >= (unsigned)(profilerInterval_ * 1000.0f))
         {
+            profilerTimer_.Reset();
+
             if (profilerText_->IsVisible())
             {
-                String profilerOutput = profiler->GetData(false, true, false);
+                String profilerOutput = profiler->GetData(false, true, false, profilerMaxDepth_);
                 profilerText_->SetText(profilerOutput);
             }
-            
-            profilerTimer_ -= profilerInterval_;
+
             profiler->ClearAccumulated();
         }
     }
@@ -215,10 +212,11 @@ void DebugHud::SetMode(unsigned mode)
     statsText_->SetVisible((mode & DEBUGHUD_SHOW_STATS) != 0);
     modeText_->SetVisible((mode & DEBUGHUD_SHOW_MODE) != 0);
     profilerText_->SetVisible((mode & DEBUGHUD_SHOW_PROFILER) != 0);
-    
-    // If profiler text is made visible, force update
-    if (profilerText_->IsVisible())
-        profilerTimer_ = profilerInterval_;
+}
+
+void DebugHud::SetProfilerMaxDepth(unsigned depth)
+{
+    profilerMaxDepth_ = depth;
 }
 
 void DebugHud::SetProfilerInterval(float interval)
@@ -259,5 +257,5 @@ void DebugHud::HandleUpdate(StringHash eventType, VariantMap& eventData)
 {
     using namespace Update;
     
-    Update(eventData[P_TIMESTEP].GetFloat());
+    Update();
 }

+ 10 - 3
Engine/Engine/DebugHud.h

@@ -24,6 +24,7 @@
 #pragma once
 
 #include "Object.h"
+#include "Timer.h"
 
 class Engine;
 class Font;
@@ -48,11 +49,13 @@ public:
     ~DebugHud();
     
     /// Update. Called by HandleUpdate().
-    void Update(float timeStep);
+    void Update();
     /// %Set UI elements' style from an XML file.
     void SetStyle(XMLFile* style);
     /// %Set elements to show.
     void SetMode(unsigned mode);
+    /// %Set maximum profiler block depth, default unlimited.
+    void SetProfilerMaxDepth(unsigned depth);
     /// %Set profiler accumulation interval.
     void SetProfilerInterval(float interval);
     /// %Set whether to show 3D geometry primitive/batch count only. Default false.
@@ -72,6 +75,8 @@ public:
     Text* GetProfilerText() const { return profilerText_; }
     /// Return currently shown elements.
     unsigned GetMode() const;
+    /// Return maximum profiler block depth.
+    unsigned GetProfilerMaxDepth() const { return profilerMaxDepth_; }
     /// Return profiler accumulation interval.
     float GetProfilerInterval() const { return profilerInterval_; }
     /// Return whether showing 3D geometry primitive/batch count only.
@@ -89,10 +94,12 @@ private:
     SharedPtr<Text> modeText_;
     /// Profiling information text.
     SharedPtr<Text> profilerText_;
+    /// Profiler accumulation timer.
+    Timer profilerTimer_;
+    /// Profiler max block depth.
+    unsigned profilerMaxDepth_;
     /// Profiler accumulation interval.
     float profilerInterval_;
-    /// Profiler accumulation timer.
-    float profilerTimer_;
     /// Show 3D geometry primitive/batch count flag.
     bool useRendererStats_;
 };

+ 4 - 0
Engine/Engine/Engine.cpp

@@ -376,6 +376,8 @@ void Engine::DumpResources()
 
 void Engine::Update()
 {
+    PROFILE(Update);
+
     // Logic update event
     using namespace Update;
     
@@ -395,6 +397,8 @@ void Engine::Update()
 
 void Engine::Render()
 {
+    PROFILE(Render);
+
     // Do not render if device lost
     Graphics* graphics = GetSubsystem<Graphics>();
     if (graphics && graphics->BeginFrame())

+ 2 - 0
Engine/Engine/EngineAPI.cpp

@@ -72,6 +72,8 @@ static void RegisterDebugHud(asIScriptEngine* engine)
     engine->RegisterObjectMethod("DebugHud", "XMLFile@+ get_style() const", asMETHOD(DebugHud, GetStyle), asCALL_THISCALL);
     engine->RegisterObjectMethod("DebugHud", "void set_mode(uint)", asMETHOD(DebugHud, SetMode), asCALL_THISCALL);
     engine->RegisterObjectMethod("DebugHud", "uint get_mode() const", asMETHOD(DebugHud, GetMode), asCALL_THISCALL);
+    engine->RegisterObjectMethod("DebugHud", "void set_profilerMaxDepth(uint)", asMETHOD(DebugHud, SetProfilerMaxDepth), asCALL_THISCALL);
+    engine->RegisterObjectMethod("DebugHud", "uint get_profilerMaxDepth() const", asMETHOD(DebugHud, GetProfilerMaxDepth), asCALL_THISCALL);
     engine->RegisterObjectMethod("DebugHud", "void set_profilerInterval(float)", asMETHOD(DebugHud, SetProfilerInterval), asCALL_THISCALL);
     engine->RegisterObjectMethod("DebugHud", "float get_profilerInterval() const", asMETHOD(DebugHud, GetProfilerInterval), asCALL_THISCALL);
     engine->RegisterObjectMethod("DebugHud", "void set_useRendererStats(bool)", asMETHOD(DebugHud, SetUseRendererStats), asCALL_THISCALL);