Bladeren bron

Added EventProfiler

- EventProfiler is based on the normal profiler
- encapsulated between URHO3D_PROFILING blocks
- added "EventProfiler" to the engineParameters and is default false
- can be activated and deactivated (should be reworked)

Added EventProfiler

- EventProfiler is based on the normal profiler
- encapsulated between URHO3D_PROFILING blocks
- added "EventProfiler" to the engineParameters and is default false
- can be activated and deactivated (should be reworked)
svifylabs 9 jaren geleden
bovenliggende
commit
bffb89b60d

+ 1 - 0
Source/Urho3D/AngelScript/EngineAPI.cpp

@@ -76,6 +76,7 @@ static void RegisterDebugHud(asIScriptEngine* engine)
     engine->RegisterGlobalProperty("const uint DEBUGHUD_SHOW_STATS", (void*)&DEBUGHUD_SHOW_STATS);
     engine->RegisterGlobalProperty("const uint DEBUGHUD_SHOW_MODE", (void*)&DEBUGHUD_SHOW_MODE);
     engine->RegisterGlobalProperty("const uint DEBUGHUD_SHOW_PROFILER", (void*)&DEBUGHUD_SHOW_PROFILER);
+    engine->RegisterGlobalProperty("const uint DEBUGHUD_SHOW_EVENTPROFILER", (void*)&DEBUGHUD_SHOW_EVENTPROFILER);
     engine->RegisterGlobalProperty("const uint DEBUGHUD_SHOW_MEMORY", (void*)&DEBUGHUD_SHOW_MEMORY);
     engine->RegisterGlobalProperty("const uint DEBUGHUD_SHOW_ALL", (void*)&DEBUGHUD_SHOW_ALL);
     engine->RegisterGlobalProperty("const uint DEBUGHUD_SHOW_ALL_MEMORY", (void*)&DEBUGHUD_SHOW_ALL_MEMORY);

+ 183 - 0
Source/Urho3D/Core/EventProfiler.cpp

@@ -0,0 +1,183 @@
+//
+// Copyright (c) 2008-2016 the Urho3D project.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//
+
+#include "../Precompiled.h"
+
+#include "../Core/CoreEvents.h"
+#include "../Core/EventProfiler.h"
+
+#include <cstdio>
+
+#include "../DebugNew.h"
+
+namespace Urho3D
+{
+
+static const int LINE_MAX_LENGTH = 256;
+static const int NAME_MAX_LENGTH = 30;
+
+EventProfiler::EventProfiler(Context* context) : 
+    Object(context),
+    active_(false),
+    current_(0),
+    root_(0),
+    intervalFrames_(0),
+    totalFrames_(0)
+{
+    root_ = new EventProfilerBlock(0, "Root");
+    current_ = root_;
+    current_->name_ = "Root";
+}
+
+EventProfiler::~EventProfiler()
+{
+    delete root_;
+    root_ = 0;
+}
+
+void EventProfiler::SetActive(bool active)
+{
+    if (!active && active_)
+    {
+        /// deleting all blocks and creating new root block.
+        delete root_;
+        root_ = 0;
+        root_ = new EventProfilerBlock(0, "Root");
+        current_ = root_;
+        current_->name_ = "Root";
+    }
+    
+    active_ = active;
+}
+
+void EventProfiler::BeginFrame()
+{
+    if (!active_)
+        return;
+    // End the previous frame if any
+    EndFrame();
+
+    BeginBlock("RunFrame");
+    current_->name_ = "RunFrame";
+}
+
+void EventProfiler::EndFrame()
+{
+    if (!active_)
+        return;
+    if (current_ != root_)
+    {
+        EndBlock();
+        ++intervalFrames_;
+        ++totalFrames_;
+        if (!totalFrames_)
+            ++totalFrames_;
+        root_->EndFrame();
+        current_ = root_;
+    }
+}
+
+void EventProfiler::BeginInterval()
+{
+    if (!active_)
+        return;
+    root_->BeginInterval();
+    intervalFrames_ = 0;
+}
+
+Urho3D::String EventProfiler::PrintData(bool showUnused /*= false*/, bool showTotal /*= false*/, unsigned maxDepth /*= M_MAX_UNSIGNED*/) const
+{
+    String output;
+
+    if (!showTotal)
+        output += "Block                            Cnt     Avg      Max     Frame     Total\n\n";
+    else
+    {
+        output += "Block                                       Last frame                       Whole execution time\n\n";
+        output += "                                 Cnt     Avg      Max      Total      Cnt      Avg       Max        Total\n\n";
+    }
+
+    if (!maxDepth)
+        maxDepth = 1;
+
+    PrintData(root_, output, 0, maxDepth, showUnused, showTotal);
+
+    return output;
+}
+
+void EventProfiler::PrintData(EventProfilerBlock* block, String& output, unsigned depth, unsigned maxDepth, bool showUnused, bool showTotal) const
+{
+    char line[LINE_MAX_LENGTH];
+    char indentedName[LINE_MAX_LENGTH];
+
+    unsigned intervalFrames = Max(intervalFrames_, 1U);
+
+    if (depth >= maxDepth)
+        return;
+
+    // Do not print the root block as it does not collect any actual data
+    if (block != root_)
+    {
+        if (showUnused || block->intervalCount_ || (showTotal && block->totalCount_))
+        {
+            memset(indentedName, ' ', NAME_MAX_LENGTH);
+            indentedName[depth] = 0;
+
+            strcat(indentedName, block->name_.Empty() ? block->eventID_.ToString().CString() : block->name_.CString());
+            indentedName[strlen(indentedName)] = ' ';
+            indentedName[NAME_MAX_LENGTH] = 0;
+
+            if (!showTotal)
+            {
+                float avg = (block->intervalCount_ ? block->intervalTime_ / block->intervalCount_ : 0.0f) / 1000.0f;
+                float max = block->intervalMaxTime_ / 1000.0f;
+                float frame = block->intervalTime_ / intervalFrames / 1000.0f;
+                float all = block->intervalTime_ / 1000.0f;
+
+                sprintf(line, "%s %5u %8.3f %8.3f %8.3f %9.3f\n", indentedName, Min(block->intervalCount_, 99999U),
+                    avg, max, frame, all);
+            }
+            else
+            {
+                float avg = (block->frameCount_ ? block->frameTime_ / block->frameCount_ : 0.0f) / 1000.0f;
+                float max = block->frameMaxTime_ / 1000.0f;
+                float all = block->frameTime_ / 1000.0f;
+
+                float totalAvg = (block->totalCount_ ? block->totalTime_ / block->totalCount_ : 0.0f) / 1000.0f;
+                float totalMax = block->totalMaxTime_ / 1000.0f;
+                float totalAll = block->totalTime_ / 1000.0f;
+
+                sprintf(line, "%s %5u %8.3f %8.3f %9.3f  %7u %9.3f %9.3f %11.3f\n", indentedName, Min(block->frameCount_, 99999U),
+                    avg, max, all, Min(block->totalCount_, 99999U), totalAvg, totalMax, totalAll);
+            }
+
+            output += String(line);
+        }
+
+        ++depth;
+    }
+
+    for (HashMap<StringHash, EventProfilerBlock*>::ConstIterator i = block->children_.Begin(); i != block->children_.End(); ++i)
+        PrintData(i->second_, output, depth, maxDepth, showUnused, showTotal);
+}
+
+}

+ 258 - 0
Source/Urho3D/Core/EventProfiler.h

@@ -0,0 +1,258 @@
+//
+// Copyright (c) 2008-2016 the Urho3D project.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//
+
+#pragma once
+
+#include "../Container/Str.h"
+#include "../Core/Thread.h"
+#include "../Core/Timer.h"
+
+#include "../Core/Profiler.h"
+
+
+namespace Urho3D
+{
+/// Event profiling data for one block in the event profiling tree.
+class URHO3D_API EventProfilerBlock
+{
+public:
+    /// Construct with the specified parent block and name.
+    EventProfilerBlock(EventProfilerBlock* parent, StringHash eventID) :
+        eventID_(eventID),
+        name_(0),
+        time_(0),
+        maxTime_(0),
+        count_(0),
+        parent_(parent),
+        frameTime_(0),
+        frameMaxTime_(0),
+        frameCount_(0),
+        intervalTime_(0),
+        intervalMaxTime_(0),
+        intervalCount_(0),
+        totalTime_(0),
+        totalMaxTime_(0),
+        totalCount_(0)
+    {
+        name_ = EventNameRegistrar::GetEventName(eventID);
+    }
+
+    /// Destruct. Free the child blocks.
+    ~EventProfilerBlock()
+    {
+        for (HashMap<StringHash, EventProfilerBlock* >::Iterator i = children_.Begin(); i != children_.End(); ++i)
+        {
+            delete i->second_;
+            i->second_ = 0;
+        }
+    }
+
+    /// Begin timing.
+    void Begin()
+    {
+        timer_.Reset();
+        ++count_;
+    }
+
+    /// End timing.
+    void End()
+    {
+        long long time = timer_.GetUSec(false);
+        if (time > maxTime_)
+            maxTime_ = time;
+        time_ += time;
+    }
+
+    /// End profiling frame and update interval and total values.
+    void EndFrame()
+    {
+        frameTime_ = time_;
+        frameMaxTime_ = maxTime_;
+        frameCount_ = count_;
+        intervalTime_ += time_;
+        if (maxTime_ > intervalMaxTime_)
+            intervalMaxTime_ = maxTime_;
+        intervalCount_ += count_;
+        totalTime_ += time_;
+        if (maxTime_ > totalMaxTime_)
+            totalMaxTime_ = maxTime_;
+        totalCount_ += count_;
+        time_ = 0;
+        maxTime_ = 0;
+        count_ = 0;
+
+        for (HashMap<StringHash, EventProfilerBlock* >::Iterator i = children_.Begin(); i != children_.End(); ++i)
+            i->second_->EndFrame();
+    }
+
+    /// Begin new profiling interval.
+    void BeginInterval()
+    {
+        intervalTime_ = 0;
+        intervalMaxTime_ = 0;
+        intervalCount_ = 0;
+
+        for (HashMap<StringHash, EventProfilerBlock*>::Iterator i = children_.Begin(); i != children_.End(); ++i)
+            i->second_->BeginInterval();
+    }
+
+    /// Return child block with the specified name.
+    EventProfilerBlock* GetChild(StringHash eventID)
+    {
+        HashMap<StringHash, EventProfilerBlock*>::Iterator it = children_.Find(eventID);
+        if (it != children_.End())
+            return it->second_;
+
+        EventProfilerBlock* newBlock = new EventProfilerBlock(this, eventID);
+        children_[eventID] = newBlock;
+
+        return newBlock;
+    }
+    /// Event ID.
+    StringHash eventID_;
+    /// Block name.
+    String name_;
+    /// High-resolution timer for measuring the block duration.
+    HiresTimer timer_;
+    /// Time on current frame.
+    long long time_;
+    /// Maximum time on current frame.
+    long long maxTime_;
+    /// Calls on current frame.
+    unsigned count_;
+    /// Parent block.
+    EventProfilerBlock* parent_;
+    /// Child blocks.
+    HashMap<StringHash,EventProfilerBlock*> children_;
+    /// Time on the previous frame.
+    long long frameTime_;
+    /// Maximum time on the previous frame.
+    long long frameMaxTime_;
+    /// Calls on the previous frame.
+    unsigned frameCount_;
+    /// Time during current profiler interval.
+    long long intervalTime_;
+    /// Maximum time during current profiler interval.
+    long long intervalMaxTime_;
+    /// Calls during current profiler interval.
+    unsigned intervalCount_;
+    /// Total accumulated time.
+    long long totalTime_;
+    /// All-time maximum time.
+    long long totalMaxTime_;
+    /// Total accumulated calls.
+    unsigned totalCount_;
+};
+
+/// Hierarchical performance profiler subsystem.
+class URHO3D_API EventProfiler : public Object
+{
+    URHO3D_OBJECT(EventProfiler, Object);
+
+public:
+    /// Construct.
+    EventProfiler(Context* context);
+    /// Destruct.
+    virtual ~EventProfiler();
+
+    /// Activate the event profiler to collect information. Request deactivation, will delete all blocks!
+    void SetActive(bool active);
+    /// Return true if active.
+    bool IsActive() const { return active_; }
+
+    /// Begin timing a profiling block.
+    void BeginBlock(StringHash eventID)
+    {
+        // Profiler supports only the main thread currently
+        if (!active_ || !Thread::IsMainThread())
+            return;
+
+        current_ = current_->GetChild(eventID);
+        current_->Begin();
+    }
+
+    /// End timing the current profiling block.
+    void EndBlock()
+    {
+        if (!active_ || !Thread::IsMainThread())
+            return;
+
+        if (current_ != root_)
+        {
+            current_->End();
+            current_ = current_->parent_;
+        }
+    }
+
+    /// Begin the profiling frame. Called by HandleBeginFrame().
+    void BeginFrame();
+    /// End the profiling frame. Called by HandleEndFrame().
+    void EndFrame();
+    /// Begin a new interval.
+    void BeginInterval();
+
+    /// Return profiling data as text output.
+    String PrintData(bool showUnused = false, bool showTotal = false, unsigned maxDepth = M_MAX_UNSIGNED) const;
+    /// Return the current profiling block.
+    const EventProfilerBlock* GetCurrentBlock() { return current_; }
+    /// Return the root profiling block.
+    const EventProfilerBlock* GetRootBlock() { return root_; }
+private:
+    /// Return profiling data as text output for a specified profiling block.
+    void PrintData(EventProfilerBlock* block, String& output, unsigned depth, unsigned maxDepth, bool showUnused, bool showTotal) const;
+    /// Is the profiler collecting event information.
+    bool active_;
+    /// Current profiling block.
+    EventProfilerBlock* current_;
+    /// Root profiling block.
+    EventProfilerBlock* root_;
+    /// Frames in the current interval.
+    unsigned intervalFrames_;
+    /// Total frames.
+    unsigned totalFrames_;
+};
+
+/// Helper class for automatically beginning and ending a profiling block
+class URHO3D_API AutoEventProfileBlock
+{
+public:
+    /// Construct. Begin a profiling block with the specified name and optional call count.
+    AutoEventProfileBlock(EventProfiler* profiler, StringHash eventID) :
+        profiler_(profiler)
+    {
+        if (profiler_)
+            profiler_->BeginBlock(eventID);
+    }
+
+    /// Destruct. End the profiling block.
+    ~AutoEventProfileBlock()
+    {
+        if (profiler_)
+            profiler_->EndBlock();
+    }
+
+private:
+    /// Profiler.
+    EventProfiler* profiler_;
+};
+
+}

+ 33 - 1
Source/Urho3D/Core/Object.cpp

@@ -1,4 +1,3 @@
-
 //
 // Copyright (c) 2008-2016 the Urho3D project.
 //
@@ -26,9 +25,12 @@
 #include "../Core/Context.h"
 #include "../Core/Thread.h"
 #include "../IO/Log.h"
+#include "../Core/EventProfiler.h"
+#include "../Container/HashMap.h"
 
 #include "../DebugNew.h"
 
+
 namespace Urho3D
 {
 
@@ -302,6 +304,11 @@ void Object::SendEvent(StringHash eventType, VariantMap& eventData)
         URHO3D_LOGERROR("Sending events is only supported from the main thread");
         return;
     }
+#ifdef URHO3D_PROFILING
+    EventProfiler* eventProfiler = GetSubsystem<EventProfiler>();
+    if (eventProfiler)
+        eventProfiler->BeginBlock(eventType);
+#endif
 
     // Make a weak pointer to self to check for destruction during event handling
     WeakPtr<Object> self(this);
@@ -398,6 +405,11 @@ void Object::SendEvent(StringHash eventType, VariantMap& eventData)
     }
 
     context->EndSendEvent();
+
+#ifdef URHO3D_PROFILING
+    if (eventProfiler)
+        eventProfiler->EndBlock();
+#endif
 }
 
 VariantMap& Object::GetEventDataMap() const
@@ -535,4 +547,24 @@ void Object::RemoveEventSender(Object* sender)
     }
 }
 
+
+Urho3D::StringHash EventNameRegistrar::RegisterEventName(const char* eventName)
+{  
+    StringHash id(eventName);
+    GetEventNameMap()[id] = eventName;
+    return id;
+}
+
+const String& EventNameRegistrar::GetEventName(StringHash eventID) 
+{
+    HashMap<StringHash, String>::ConstIterator it = GetEventNameMap().Find(eventID);
+    return  it != GetEventNameMap().End() ? it->second_ : String::EMPTY ;
+}
+
+HashMap<StringHash, String>& EventNameRegistrar::GetEventNameMap()
+{
+    static HashMap<StringHash, String> eventNames_;
+    return eventNames_;
+}
+
 }

+ 11 - 1
Source/Urho3D/Core/Object.h

@@ -356,8 +356,18 @@ private:
 };
 #endif
 
+/// Register event names.
+struct EventNameRegistrar
+{
+    static StringHash RegisterEventName(const char* eventName);
+    /// Return Event name or empty string if not found.
+    static const String& GetEventName(StringHash eventID );
+    /// Return Event name map.
+    static HashMap<StringHash, String>& GetEventNameMap();
+};
+
 /// Describe an event's hash ID and begin a namespace in which to define its parameters.
-#define URHO3D_EVENT(eventID, eventName) static const Urho3D::StringHash eventID(#eventName); namespace eventName
+#define URHO3D_EVENT(eventID, eventName) static const Urho3D::StringHash eventID(EventNameRegistrar::RegisterEventName(#eventName)); namespace eventName
 /// Describe an event's parameter hash ID. Should be used inside an event namespace.
 #define URHO3D_PARAM(paramID, paramName) static const Urho3D::StringHash paramID(#paramName)
 /// Convenience macro to construct an EventHandler that points to a receiver object and its member function.

+ 40 - 1
Source/Urho3D/Engine/DebugHud.cpp

@@ -24,6 +24,8 @@
 
 #include "../Core/CoreEvents.h"
 #include "../Core/Profiler.h"
+#include "../Core/EventProfiler.h"
+#include "../Core/Context.h"
 #include "../Engine/DebugHud.h"
 #include "../Engine/Engine.h"
 #include "../Graphics/Graphics.h"
@@ -90,6 +92,12 @@ DebugHud::DebugHud(Context* context) :
     memoryText_->SetVisible(false);
     uiRoot->AddChild(memoryText_);
 
+    eventProfilerText_ = new Text(context_);
+    eventProfilerText_->SetAlignment(HA_RIGHT, VA_TOP);
+    eventProfilerText_->SetPriority(100);
+    eventProfilerText_->SetVisible(false);
+    uiRoot->AddChild(eventProfilerText_);
+
     SubscribeToEvent(E_POSTUPDATE, URHO3D_HANDLER(DebugHud, HandlePostUpdate));
 }
 
@@ -99,6 +107,7 @@ DebugHud::~DebugHud()
     modeText_->Remove();
     profilerText_->Remove();
     memoryText_->Remove();
+    eventProfilerText_->Remove();
 }
 
 void DebugHud::Update()
@@ -169,6 +178,7 @@ void DebugHud::Update()
     }
 
     Profiler* profiler = GetSubsystem<Profiler>();
+    EventProfiler* eventProfiler = GetSubsystem<EventProfiler>();
     if (profiler)
     {
         if (profilerTimer_.GetMSec(false) >= profilerInterval_)
@@ -182,6 +192,17 @@ void DebugHud::Update()
             }
 
             profiler->BeginInterval();
+
+            if (eventProfiler)
+            {
+                if (eventProfilerText_->IsVisible())
+                {
+                    String profilerOutput = eventProfiler->PrintData(false, false, profilerMaxDepth_);
+                    eventProfilerText_->SetText(profilerOutput);
+                }
+
+                eventProfiler->BeginInterval();
+            }
         }
     }
 
@@ -205,6 +226,8 @@ void DebugHud::SetDefaultStyle(XMLFile* style)
     profilerText_->SetStyle("DebugHudText");
     memoryText_->SetDefaultStyle(style);
     memoryText_->SetStyle("DebugHudText");
+    eventProfilerText_->SetDefaultStyle(style);
+    eventProfilerText_->SetStyle("DebugHudText");
 }
 
 void DebugHud::SetMode(unsigned mode)
@@ -213,7 +236,23 @@ void DebugHud::SetMode(unsigned mode)
     modeText_->SetVisible((mode & DEBUGHUD_SHOW_MODE) != 0);
     profilerText_->SetVisible((mode & DEBUGHUD_SHOW_PROFILER) != 0);
     memoryText_->SetVisible((mode & DEBUGHUD_SHOW_MEMORY) != 0);
-
+    eventProfilerText_->SetVisible((mode & DEBUGHUD_SHOW_EVENTPROFILER) != 0);
+#ifdef URHO3D_PROFILING
+    if ((mode & DEBUGHUD_SHOW_EVENTPROFILER) != 0)
+    {
+        EventProfiler* eventProfiler = GetSubsystem<EventProfiler>();
+        if (!eventProfiler)
+            context_->RegisterSubsystem(eventProfiler = new EventProfiler(context_));
+        if (eventProfiler)
+            eventProfiler->SetActive(true);
+    }
+    else
+    {
+        EventProfiler* eventProfiler = GetSubsystem<EventProfiler>();
+        if (eventProfiler)
+            eventProfiler->SetActive(false);
+    }
+#endif
     mode_ = mode;
 }
 

+ 3 - 0
Source/Urho3D/Engine/DebugHud.h

@@ -40,6 +40,7 @@ static const unsigned DEBUGHUD_SHOW_PROFILER = 0x4;
 static const unsigned DEBUGHUD_SHOW_MEMORY = 0x8;
 static const unsigned DEBUGHUD_SHOW_ALL = 0x7;
 static const unsigned DEBUGHUD_SHOW_ALL_MEMORY = 0xB;
+static const unsigned DEBUGHUD_SHOW_EVENTPROFILER = 0x10;
 
 /// Displays rendering stats and profiling information.
 class URHO3D_API DebugHud : public Object
@@ -115,6 +116,8 @@ private:
     SharedPtr<Text> modeText_;
     /// Profiling information text.
     SharedPtr<Text> profilerText_;
+    /// Event profiling information text.
+    SharedPtr<Text> eventProfilerText_;
     /// Memory stats text.
     SharedPtr<Text> memoryText_;
     /// Hashmap containing application specific stats.

+ 19 - 2
Source/Urho3D/Engine/Engine.cpp

@@ -27,6 +27,7 @@
 #include "../Core/CoreEvents.h"
 #include "../Core/ProcessUtils.h"
 #include "../Core/Profiler.h"
+#include "../Core/EventProfiler.h"
 #include "../Core/WorkQueue.h"
 #include "../Engine/Console.h"
 #include "../Engine/DebugHud.h"
@@ -64,6 +65,7 @@
 
 #include "../DebugNew.h"
 
+
 #if defined(_MSC_VER) && defined(_DEBUG)
 // From dbgint.h
 #define nNoMansLandSize 4
@@ -422,7 +424,14 @@ bool Engine::Initialize(const VariantMap& parameters)
             SharedPtr<Object> object = i->second_->CreateObject();
     }
 #endif
-
+#ifdef URHO3D_PROFILING
+    if (GetParameter(parameters, "EventProfiler", true).GetBool())
+    {
+        EventProfiler* evpr = new EventProfiler(context_);
+        context_->RegisterSubsystem(evpr);
+        evpr->SetActive(true);
+    }
+#endif
     frameTimer_.Reset();
 
     URHO3D_LOGINFO("Initialized engine");
@@ -446,7 +455,11 @@ void Engine::RunFrame()
     Time* time = GetSubsystem<Time>();
     Input* input = GetSubsystem<Input>();
     Audio* audio = GetSubsystem<Audio>();
-
+#ifdef URHO3D_PROFILING
+    EventProfiler* eventProfiler = GetSubsystem<EventProfiler>();
+    if (eventProfiler)
+        eventProfiler->BeginFrame();
+#endif
     time->BeginFrame(timeStep_);
 
     // If pause when minimized -mode is in use, stop updates and audio as necessary
@@ -474,6 +487,10 @@ void Engine::RunFrame()
     ApplyFrameLimit();
 
     time->EndFrame();
+#ifdef URHO3D_PROFILING
+    if (eventProfiler)
+        eventProfiler->EndFrame();
+#endif
 }
 
 Console* Engine::CreateConsole()

+ 11 - 0
bin/Data/Scripts/NinjaSnowWar.as

@@ -489,6 +489,17 @@ void HandleKeyDown(StringHash eventType, VariantMap& eventData)
     if (key == KEY_F4)
         drawOctreeDebug = !drawOctreeDebug;
 
+    if (key == KEY_F5)
+        debugHud.Toggle(DEBUGHUD_SHOW_EVENTPROFILER);
+                // Take screenshot
+    if (key == KEY_F6)
+    {
+        Image@ screenshot = Image();
+        graphics.TakeScreenShot(screenshot);
+        // Here we save in the Data folder with date and time appended
+        screenshot.SavePNG(fileSystem.programDir + "Data/Screenshot_" +
+                time.timeStamp.Replaced(':', '_').Replaced('.', '_').Replaced(' ', '_') + ".png");
+    }
     // Allow pause only in singleplayer
     if (key == 'P' && singlePlayer && !console.visible && gameOn)
     {