Ver Fonte

Display more runtime stats

Panagiotis Christopoulos Charitos há 7 anos atrás
pai
commit
a17423552f

+ 72 - 22
src/anki/core/App.cpp

@@ -40,9 +40,41 @@ android_app* gAndroidApp = nullptr;
 class App::StatsUi : public UiImmediateModeBuilder
 {
 public:
-	Second m_frameTime = 0.0;
-	Second m_totalFrameTime = 0.0;
-	Second m_avgFrameTime = 0.0;
+	template<typename T>
+	class BufferedValue
+	{
+	public:
+		void set(T x)
+		{
+			m_total += x;
+			++m_count;
+		}
+
+		F64 get(Bool flush)
+		{
+			if(flush)
+			{
+				m_avg = F64(m_total) / m_count;
+				m_count = 0;
+				m_total = 0.0;
+			}
+
+			return m_avg;
+		}
+
+	private:
+		T m_total = T(0);
+		F64 m_avg = 0.0;
+		U32 m_count = 0;
+	};
+
+	BufferedValue<Second> m_frameTime;
+	BufferedValue<Second> m_renderTime;
+	BufferedValue<Second> m_lightBinTime;
+	BufferedValue<Second> m_sceneUpdateTime;
+	BufferedValue<Second> m_visTestsTime;
+
+	static const U32 BUFFERED_FRAMES = 16;
 	U32 m_bufferedFrames = 0;
 
 	StatsUi(UiManager* ui)
@@ -52,35 +84,44 @@ public:
 
 	void build(CanvasPtr canvas)
 	{
+		// Misc
+		++m_bufferedFrames;
+		Bool flush = false;
+		if(m_bufferedFrames == BUFFERED_FRAMES)
+		{
+			flush = true;
+			m_bufferedFrames = 0;
+		}
+
+		// Start drawing the UI
 		nk_context* ctx = &canvas->getNkContext();
 
+		canvas->pushFont(canvas->getDefaultFont(), 16);
+
 		nk_style_push_style_item(
 			ctx, &ctx->style.window.fixed_background, nk_style_item_color(nk_rgba(255, 255, 255, 0)));
 
-		if(nk_begin(ctx, "Stats", nk_rect(5, 5, 100, 200), 0))
+		if(nk_begin(ctx, "Stats", nk_rect(5, 5, 200, 200), 0))
 		{
-			nk_layout_row_dynamic(ctx, 30, 1);
-
-			// Frametime
-			const U32 BUFFERED_FRAMES = 16;
-			m_totalFrameTime += m_frameTime;
-			++m_bufferedFrames;
-
-			if(m_bufferedFrames == BUFFERED_FRAMES)
-			{
-				m_avgFrameTime = m_totalFrameTime / BUFFERED_FRAMES;
-				m_bufferedFrames = 0;
-				m_totalFrameTime = 0.0;
-			}
+			nk_layout_row_dynamic(ctx, 17, 1);
 
-			StringAuto timestamp(getAllocator());
-			timestamp.sprintf("Frametime: %f", m_avgFrameTime * 1000.0);
-			nk_label(ctx, timestamp.cstr(), NK_TEXT_ALIGN_LEFT);
+			labelTime(ctx, m_frameTime, "Frame", flush);
+			labelTime(ctx, m_renderTime, "Renderer", flush);
+			labelTime(ctx, m_lightBinTime, "Light bin", flush);
+			labelTime(ctx, m_sceneUpdateTime, "Scene update", flush);
+			labelTime(ctx, m_visTestsTime, "Visibility", flush);
 		}
 
 		nk_style_pop_style_item(ctx);
-
 		nk_end(ctx);
+		canvas->popFont();
+	}
+
+	void labelTime(nk_context* ctx, BufferedValue<Second>& val, CString name, Bool flush)
+	{
+		StringAuto timestamp(getAllocator());
+		timestamp.sprintf("%s: %fms", name.cstr(), val.get(flush) * 1000.0);
+		nk_label(ctx, timestamp.cstr(), NK_TEXT_ALIGN_LEFT);
 	}
 };
 
@@ -202,6 +243,8 @@ Error App::initInternal(const ConfigSet& config_, AllocAlignedCallback allocCb,
 	m_heapAlloc = HeapAllocator<U8>(allocCb, allocCbUserData);
 	ConfigSet config = config_;
 
+	m_displayStats = config.getNumber("core.displayStats");
+
 	ANKI_CHECK(initDirs(config));
 
 	// Print a message
@@ -485,13 +528,20 @@ Error App::mainLoop()
 		// Sleep
 		const Second endTime = HighRezTimer::getCurrentTime();
 		const Second frameTime = endTime - startTime;
-		static_cast<StatsUi&>(*m_statsUi).m_frameTime = frameTime;
 		if(frameTime < m_timerTick)
 		{
 			ANKI_TRACE_SCOPED_EVENT(TIMER_TICK_SLEEP);
 			HighRezTimer::sleep(m_timerTick - frameTime);
 		}
 
+		// Stats
+		StatsUi& statsUi = static_cast<StatsUi&>(*m_statsUi);
+		statsUi.m_frameTime.set(frameTime);
+		statsUi.m_renderTime.set(m_renderer->getStats().m_renderingTime);
+		statsUi.m_lightBinTime.set(m_renderer->getStats().m_lightBinTime);
+		statsUi.m_sceneUpdateTime.set(m_scene->getStats().m_updateTime);
+		statsUi.m_visTestsTime.set(m_scene->getStats().m_visibilityTestsTime);
+
 		++m_globalTimestamp;
 
 		ANKI_TRACE_STOP_FRAME();

+ 1 - 0
src/anki/core/Config.cpp

@@ -71,6 +71,7 @@ Config::Config()
 	newOption("core.vertexPerFrameMemorySize", 10_MB);
 	newOption("core.textureBufferPerFrameMemorySize", 1_MB);
 	newOption("core.mainThreadCount", getCpuCoresCount());
+	newOption("core.displayStats", false);
 }
 
 Config::~Config()

+ 7 - 1
src/anki/renderer/MainRenderer.cpp

@@ -4,7 +4,6 @@
 // http://www.anki3d.org/LICENSE
 
 #include <anki/renderer/MainRenderer.h>
-#include <anki/renderer/Renderer.h>
 #include <anki/renderer/LightShading.h>
 #include <anki/renderer/FinalComposite.h>
 #include <anki/renderer/Dbg.h>
@@ -17,6 +16,7 @@
 #include <anki/core/Trace.h>
 #include <anki/core/App.h>
 #include <anki/misc/ConfigSet.h>
+#include <anki/util/HighRezTimer.h>
 
 namespace anki
 {
@@ -83,6 +83,8 @@ Error MainRenderer::render(RenderQueue& rqueue)
 {
 	ANKI_TRACE_SCOPED_EVENT(RENDER);
 
+	m_stats.m_renderingTime = HighRezTimer::getCurrentTime();
+
 	// First thing, reset the temp mem pool
 	m_frameAlloc.getMemoryPool().reset();
 
@@ -148,6 +150,10 @@ Error MainRenderer::render(RenderQueue& rqueue)
 	m_rgraph->reset();
 	m_r->finalize(ctx);
 
+	// Stats
+	static_cast<RendererStats&>(m_stats) = m_r->getStats();
+	m_stats.m_renderingTime = HighRezTimer::getCurrentTime() - m_stats.m_renderingTime;
+
 	return Error::NONE;
 }
 

+ 15 - 0
src/anki/renderer/MainRenderer.h

@@ -8,6 +8,7 @@
 #include <anki/renderer/Common.h>
 #include <anki/resource/Forward.h>
 #include <anki/core/Timestamp.h>
+#include <anki/renderer/Renderer.h>
 
 namespace anki
 {
@@ -22,6 +23,13 @@ class UiManager;
 /// @addtogroup renderer
 /// @{
 
+/// MainRenderer statistics.
+class MainRendererStats : public RendererStats
+{
+public:
+	Second m_renderingTime ANKI_DBG_NULLIFY;
+};
+
 /// Main onscreen renderer
 class MainRenderer
 {
@@ -56,6 +64,11 @@ public:
 		return *m_r;
 	}
 
+	const MainRendererStats& getStats() const
+	{
+		return m_stats;
+	}
+
 private:
 	HeapAllocator<U8> m_alloc;
 	StackAllocator<U8> m_frameAlloc;
@@ -73,6 +86,8 @@ private:
 
 	RenderGraphPtr m_rgraph;
 
+	MainRendererStats m_stats;
+
 	void runBlit(RenderPassWorkContext& rgraphCtx);
 
 	// A RenderPassWorkCallback for blit pass.

+ 3 - 0
src/anki/renderer/Renderer.cpp

@@ -7,6 +7,7 @@
 #include <anki/renderer/RenderQueue.h>
 #include <anki/core/Trace.h>
 #include <anki/misc/ConfigSet.h>
+#include <anki/util/HighRezTimer.h>
 
 #include <anki/renderer/Indirect.h>
 #include <anki/renderer/GBuffer.h>
@@ -283,7 +284,9 @@ Error Renderer::populateRenderGraph(RenderingContext& ctx)
 
 	m_finalComposite->populateRenderGraph(ctx);
 
+	m_stats.m_lightBinTime = HighRezTimer::getCurrentTime();
 	ANKI_CHECK(m_lightShading->binLights(ctx));
+	m_stats.m_lightBinTime = HighRezTimer::getCurrentTime() - m_stats.m_lightBinTime;
 
 	return Error::NONE;
 }

+ 21 - 6
src/anki/renderer/Renderer.h

@@ -56,6 +56,14 @@ public:
 	}
 };
 
+/// Renderer statistics.
+class RendererStats
+{
+public:
+	U32 m_drawcallCount ANKI_DBG_NULLIFY;
+	Second m_lightBinTime ANKI_DBG_NULLIFY;
+};
+
 /// Offscreen renderer. It is a class and not a namespace because we may need external renderers for security cameras
 /// for example
 class Renderer
@@ -65,12 +73,6 @@ public:
 
 	~Renderer();
 
-	UiManager& getUiManager()
-	{
-		ANKI_ASSERT(m_ui);
-		return *m_ui;
-	}
-
 	Indirect& getIndirect()
 	{
 		return *m_indirect;
@@ -193,6 +195,11 @@ public:
 
 	void finalize(const RenderingContext& ctx);
 
+	const RendererStats& getStats() const
+	{
+		return m_stats;
+	}
+
 anki_internal:
 	U64 getFrameCount() const
 	{
@@ -209,6 +216,12 @@ anki_internal:
 		return m_sceneDrawer;
 	}
 
+	UiManager& getUiManager()
+	{
+		ANKI_ASSERT(m_ui);
+		return *m_ui;
+	}
+
 	Bool getTessellationEnabled() const
 	{
 		return m_tessellation;
@@ -393,6 +406,8 @@ private:
 	SamplerPtr m_linearSampler;
 	SamplerPtr m_trilinearRepeatSampler;
 
+	RendererStats m_stats;
+
 	ANKI_USE_RESULT Error initInternal(const ConfigSet& initializer);
 
 	void initJitteredMats();

+ 2 - 2
src/anki/renderer/UiStage.cpp

@@ -23,8 +23,8 @@ UiStage::~UiStage()
 
 Error UiStage::init(const ConfigSet&)
 {
-	ANKI_CHECK(
-		m_r->getUiManager().newInstance(m_font, "engine_data/UbuntuRegular.ttf", std::initializer_list<U32>{12}));
+	ANKI_CHECK(m_r->getUiManager().newInstance(
+		m_font, "engine_data/UbuntuRegular.ttf", std::initializer_list<U32>{12, 16, 20}));
 	ANKI_CHECK(m_r->getUiManager().newInstance(m_canvas, m_font, 12, m_r->getWidth(), m_r->getHeight()));
 
 	return Error::NONE;

+ 5 - 0
src/anki/scene/SceneGraph.cpp

@@ -192,6 +192,8 @@ Error SceneGraph::update(Second prevUpdateTime, Second crntTime)
 	ANKI_ASSERT(m_mainCam);
 	ANKI_TRACE_SCOPED_EVENT(SCENE_UPDATE);
 
+	m_stats.m_updateTime = HighRezTimer::getCurrentTime();
+
 	m_timestamp = *m_globalTimestamp;
 
 	// Reset the framepool
@@ -233,12 +235,15 @@ Error SceneGraph::update(Second prevUpdateTime, Second crntTime)
 	ANKI_CHECK(threadPool.waitForAllThreadsToFinish());
 	ANKI_TRACE_STOP_EVENT(SCENE_NODES_UPDATE);
 
+	m_stats.m_updateTime = HighRezTimer::getCurrentTime() - m_stats.m_updateTime;
 	return Error::NONE;
 }
 
 void SceneGraph::doVisibilityTests(RenderQueue& rqueue)
 {
+	m_stats.m_visibilityTestsTime = HighRezTimer::getCurrentTime();
 	anki::doVisibilityTests(*m_mainCam, *this, rqueue);
+	m_stats.m_visibilityTestsTime = HighRezTimer::getCurrentTime() - m_stats.m_visibilityTestsTime;
 }
 
 Error SceneGraph::updateNode(Second prevTime, Second crntTime, SceneNode& node)

+ 15 - 0
src/anki/scene/SceneGraph.h

@@ -32,6 +32,14 @@ class UpdateSceneNodesCtx;
 /// @addtogroup scene
 /// @{
 
+/// SceneGraph statistics.
+class SceneGraphStats
+{
+public:
+	Second m_updateTime ANKI_DBG_NULLIFY;
+	Second m_visibilityTestsTime ANKI_DBG_NULLIFY;
+};
+
 /// The scene graph that  all the scene entities
 class SceneGraph
 {
@@ -162,6 +170,11 @@ public:
 		m_objectsMarkedForDeletionCount.fetchAdd(1);
 	}
 
+	const SceneGraphStats& getStats() const
+	{
+		return m_stats;
+	}
+
 anki_internal:
 	ResourceManager& getResourceManager()
 	{
@@ -253,6 +266,8 @@ private:
 
 	F32 m_earlyZDist = -1.0;
 
+	SceneGraphStats m_stats;
+
 	/// Put a node in the appropriate containers
 	ANKI_USE_RESULT Error registerNode(SceneNode* node);
 	void unregisterNode(SceneNode* node);

+ 2 - 2
src/anki/ui/Canvas.cpp

@@ -109,10 +109,10 @@ void Canvas::endBuilding()
 #endif
 }
 
-void Canvas::pushFont(FontPtr font, U32 fontHeight)
+void Canvas::pushFont(const FontPtr& font, U32 fontHeight)
 {
 	ANKI_ASSERT(m_building);
-	m_references.pushBack(m_stackAlloc, IntrusivePtr<UiObject>(font.get()));
+	m_references.pushBack(m_stackAlloc, IntrusivePtr<UiObject>(const_cast<Font*>(font.get())));
 	nk_style_push_font(&m_nkCtx, &font->getFont(fontHeight));
 }
 

+ 1 - 1
src/anki/ui/Canvas.h

@@ -55,7 +55,7 @@ public:
 	/// End building.
 	void endBuilding();
 
-	void pushFont(FontPtr font, U32 fontHeight);
+	void pushFont(const FontPtr& font, U32 fontHeight);
 
 	void popFont()
 	{

+ 1 - 1
tools/scene/Exporter.cpp

@@ -710,7 +710,7 @@ void Exporter::exportCamera(const aiCamera& cam)
 	// Write the main node
 	file << "\nnode = scene:newPerspectiveCameraNode(\"" << cam.mName.C_Str() << "\")\n";
 
-	file << "scene:setActiveCamera(node:getSceneNodeBase())\n";
+	file << "scene:setActiveCameraNode(node:getSceneNodeBase())\n";
 
 	file << "node:setAll(" << cam.mHorizontalFOV << ", "
 		 << "1.0 / getMainRenderer():getAspectRatio() * " << cam.mHorizontalFOV << ", " << cam.mClipPlaneNear << ", "