diff --git a/binaries/data/config/default.cfg b/binaries/data/config/default.cfg index 2015cc6c8a..a89a933a21 100644 --- a/binaries/data/config/default.cfg +++ b/binaries/data/config/default.cfg @@ -201,6 +201,7 @@ hotkey.text.move.right = "Ctrl+RightArrow" ; Move cursor to start of word to ; > PROFILER hotkey.profile.toggle = "F11" ; Enable/disable real-time profiler hotkey.profile.save = "Shift+F11" ; Save current profiler data to logs/profile.txt +hotkey.profile2.enable = "F11" ; Enable HTTP server for new profiler ; > QUICKSAVE hotkey.quicksave = "Shift+F5" diff --git a/source/graphics/GameView.cpp b/source/graphics/GameView.cpp index 7e17a4a103..39ad2f8416 100644 --- a/source/graphics/GameView.cpp +++ b/source/graphics/GameView.cpp @@ -483,7 +483,9 @@ void CGameView::Render() // Submit all objects visible in the given frustum void CGameView::EnumerateObjects(const CFrustum& frustum, SceneCollector* c) { - PROFILE_START("submit terrain"); + { + PROFILE3("submit terrain"); + CTerrain* pTerrain = m->Game->GetWorld()->GetTerrain(); const ssize_t patchesPerSide = pTerrain->GetPatchesPerSide(); @@ -548,11 +550,9 @@ void CGameView::EnumerateObjects(const CFrustum& frustum, SceneCollector* c) } } } - PROFILE_END("submit terrain"); + } - PROFILE_START("submit sim components"); m->Game->GetSimulation2()->RenderSubmit(*c, frustum, m->Culling); - PROFILE_END("submit sim components"); } diff --git a/source/graphics/ShaderManager.cpp b/source/graphics/ShaderManager.cpp index ad3080c701..ba270f009c 100644 --- a/source/graphics/ShaderManager.cpp +++ b/source/graphics/ShaderManager.cpp @@ -23,6 +23,7 @@ #include "lib/utf8.h" #include "ps/CLogger.h" #include "ps/Filesystem.h" +#include "ps/Profile.h" #include "ps/XML/Xeromyces.h" #include "ps/XML/XMLWriter.h" #include "renderer/Renderer.h" @@ -74,6 +75,9 @@ CShaderProgramPtr CShaderManager::LoadProgram(const char* name, const std::map& baseDefines, CShaderProgramPtr& program) { + PROFILE2("loading shader"); + PROFILE2_ATTR("name: %s", name); + if (strncmp(name, "fixed:", 6) == 0) { program = CShaderProgramPtr(CShaderProgram::ConstructFFP(name+6)); diff --git a/source/graphics/TextureConverter.cpp b/source/graphics/TextureConverter.cpp index 341276dd81..151013ce48 100644 --- a/source/graphics/TextureConverter.cpp +++ b/source/graphics/TextureConverter.cpp @@ -26,6 +26,7 @@ #include "maths/MD5.h" #include "ps/CLogger.h" #include "ps/CStr.h" +#include "ps/Profiler2.h" #include "ps/XML/Xeromyces.h" #include "nvtt/nvtt.h" @@ -486,12 +487,16 @@ bool CTextureConverter::IsBusy() void* CTextureConverter::RunThread(void* data) { debug_SetThreadName("TextureConverter"); + g_Profiler2.RegisterCurrentThread("texconv"); CTextureConverter* textureConverter = static_cast(data); // Wait until the main thread wakes us up while (SDL_SemWait(textureConverter->m_WorkerSem) == 0) { + g_Profiler2.RecordSyncMarker(); + PROFILE2_EVENT("wakeup"); + pthread_mutex_lock(&textureConverter->m_WorkerMutex); if (textureConverter->m_Shutdown) { @@ -513,9 +518,13 @@ void* CTextureConverter::RunThread(void* data) // TIMER(L"TextureConverter compress"); - // Perform the compression - nvtt::Compressor compressor; - result->ret = compressor.process(request->inputOptions, request->compressionOptions, request->outputOptions); + { + PROFILE2("compress"); + + // Perform the compression + nvtt::Compressor compressor; + result->ret = compressor.process(request->inputOptions, request->compressionOptions, request->outputOptions); + } // Ugly hack: NVTT 2.0 doesn't set DDPF_ALPHAPIXELS for DXT1a, so we can't // distinguish it from DXT1. (It's fixed in trunk by diff --git a/source/graphics/TextureManager.cpp b/source/graphics/TextureManager.cpp index fb30ec160e..791be0688b 100644 --- a/source/graphics/TextureManager.cpp +++ b/source/graphics/TextureManager.cpp @@ -29,6 +29,7 @@ #include "ps/CacheLoader.h" #include "ps/CLogger.h" #include "ps/Filesystem.h" +#include "ps/Profile.h" #include #include @@ -170,6 +171,9 @@ public: if (m_DisableGL) return; + PROFILE2("load texture"); + PROFILE2_ATTR("name: %ls", path.string().c_str()); + Handle h = ogl_tex_load(m_VFS, path, RES_UNIQUE); if (h <= 0) { @@ -285,6 +289,9 @@ public: { VfsPath sourcePath = texture->m_Properties.m_Path; + PROFILE2("convert texture"); + PROFILE2_ATTR("name: %ls", sourcePath.string().c_str()); + MD5 hash; u32 version; PrepareCacheKey(texture, hash, version); diff --git a/source/gui/GUIManager.cpp b/source/gui/GUIManager.cpp index b46cadc7a8..f7befba292 100644 --- a/source/gui/GUIManager.cpp +++ b/source/gui/GUIManager.cpp @@ -143,6 +143,10 @@ void CGUIManager::LoadPage(SGUIPage& page) } CStrW name (node.GetText().FromUTF8()); + + PROFILE2("load gui xml"); + PROFILE2_ATTR("name: %ls", name.c_str()); + TIMER(name.c_str()); VfsPath path = VfsPath("gui") / name; page.gui->LoadXmlFile(path, page.inputs); @@ -253,6 +257,8 @@ void CGUIManager::SendEventToAll(const CStr& eventName) void CGUIManager::TickObjects() { + PROFILE3("gui tick"); + // Save an immutable copy so iterators aren't invalidated by tick handlers PageStackType pageStack = m_PageStack; @@ -266,6 +272,8 @@ void CGUIManager::TickObjects() void CGUIManager::Draw() { + PROFILE3("render gui"); + for (PageStackType::iterator it = m_PageStack.begin(); it != m_PageStack.end(); ++it) it->gui->Draw(); } diff --git a/source/gui/MiniMap.cpp b/source/gui/MiniMap.cpp index ed3dd36668..05e234e277 100644 --- a/source/gui/MiniMap.cpp +++ b/source/gui/MiniMap.cpp @@ -262,7 +262,7 @@ void CMiniMap::DrawTexture(float coordMax, float angle, float x, float y, float void CMiniMap::Draw() { - PROFILE("minimap"); + PROFILE3("render minimap"); // The terrain isn't actually initialized until the map is loaded, which // happens when the game is started, so abort until then. diff --git a/source/main.cpp b/source/main.cpp index c252baa88e..ad1c9448fd 100644 --- a/source/main.cpp +++ b/source/main.cpp @@ -49,6 +49,7 @@ that of Atlas depending on commandline parameters. #include "ps/Hotkey.h" #include "ps/Loader.h" #include "ps/Profile.h" +#include "ps/Profiler2.h" #include "ps/Pyrogenesis.h" #include "ps/Replay.h" #include "ps/UserReport.h" @@ -132,6 +133,11 @@ static InReaction MainInputHandler(const SDL_Event_* ev) g_VideoMode.ToggleFullscreen(); return IN_HANDLED; } + else if (hotkey == "profile2.enable") + { + g_Profiler2.EnableHTTP(); + return IN_HANDLED; + } break; } @@ -142,7 +148,7 @@ static InReaction MainInputHandler(const SDL_Event_* ev) // dispatch all pending events to the various receivers. static void PumpEvents() { - PROFILE("dispatch events"); + PROFILE3("dispatch events"); SDL_Event_ ev; while(SDL_PollEvent(&ev.ev)) @@ -182,6 +188,8 @@ return false; static int ProgressiveLoad() { + PROFILE3("progressive load"); + wchar_t description[100]; int progress_percent; try @@ -226,6 +234,8 @@ static int ProgressiveLoad() static void RendererIncrementalLoad() { + PROFILE3("renderer incremental load"); + const double maxTime = 0.1f; double startTime = timer_Time(); @@ -241,6 +251,9 @@ static bool quit = false; // break out of main loop static void Frame() { + g_Profiler2.RecordFrameStart(); + PROFILE2("frame"); + ogl_WarnIfError(); // get elapsed time @@ -269,7 +282,7 @@ static void Frame() // debugging easier. if( !g_NetClient && !g_app_has_focus ) { - PROFILE("non-focus delay"); + PROFILE3("non-focus delay"); need_update = false; // don't use SDL_WaitEvent: don't want the main loop to freeze until app focus is restored SDL_Delay(10); @@ -279,10 +292,7 @@ static void Frame() // this is mostly relevant for "inactive" state, so that other windows // get enough CPU time, but it's always nice for power+thermal management. - bool is_building_archive; // must come before PROFILE_START's { - PROFILE_START("build archive"); - is_building_archive = ProgressiveBuildArchive(); - PROFILE_END( "build archive"); + bool is_building_archive = ProgressiveBuildArchive(); // this scans for changed files/directories and reloads them, thus // allowing hotloading (changes are immediately assimilated in-game). @@ -290,23 +300,13 @@ static void Frame() // archive file each iteration, but keeps it locked; reloading // would trigger a warning because the file can't be opened. if(!is_building_archive) - { - PROFILE_START("reload changed files"); ReloadChangedFiles(); - PROFILE_END( "reload changed files"); - } - PROFILE_START("progressive load"); ProgressiveLoad(); - PROFILE_END("progressive load"); - PROFILE_START("renderer incremental load"); RendererIncrementalLoad(); - PROFILE_END("renderer incremental load"); - PROFILE_START("input"); PumpEvents(); - PROFILE_END("input"); // if the user quit by closing the window, the GL context will be broken and // may crash when we call Render() on some drivers, so leave this loop @@ -321,16 +321,12 @@ static void Frame() g_ResizedW = g_ResizedH = 0; } - PROFILE_START("network poll"); if (g_NetClient) g_NetClient->Poll(); - PROFILE_END("network poll"); ogl_WarnIfError(); - PROFILE_START("gui tick"); g_GUI->TickObjects(); - PROFILE_END("gui tick"); ogl_WarnIfError(); @@ -338,11 +334,8 @@ static void Frame() { g_Game->Update(TimeSinceLastFrame); - PROFILE_START( "camera update" ); g_Game->GetView()->Update(float(TimeSinceLastFrame)); - PROFILE_END( "camera update" ); - PROFILE_START( "sound update" ); CCamera* camera = g_Game->GetView()->GetCamera(); CMatrix3D& orientation = camera->m_Orientation; float* pos = &orientation._data[12]; @@ -352,37 +345,37 @@ static void Frame() // is going wrong, because the listener and camera are supposed to // coincide in position and orientation. float down[3] = { -up[0], -up[1], -up[2] }; - if(snd_update(pos, dir, down) < 0) - debug_printf(L"snd_update failed\n"); - PROFILE_END( "sound update" ); + + { + PROFILE3("sound update"); + if (snd_update(pos, dir, down) < 0) + debug_printf(L"snd_update failed\n"); + } } else { - if(snd_update(0, 0, 0) < 0) + PROFILE3("sound update (0)"); + if (snd_update(0, 0, 0) < 0) debug_printf(L"snd_update (pos=0 version) failed\n"); } // Immediately flush any messages produced by simulation code - PROFILE_START("network flush"); if (g_NetClient) g_NetClient->Flush(); - PROFILE_END("network flush"); g_UserReporter.Update(); g_Console->Update(TimeSinceLastFrame); - PROFILE_START("render"); ogl_WarnIfError(); if(need_render) { Render(); - PROFILE_START( "swap buffers" ); + + PROFILE3("swap buffers"); SDL_GL_SwapBuffers(); - PROFILE_END( "swap buffers" ); } ogl_WarnIfError(); - PROFILE_END("render"); g_Profiler.Frame(); diff --git a/source/network/NetSession.cpp b/source/network/NetSession.cpp index 28ca8445fc..5d92ef0bce 100644 --- a/source/network/NetSession.cpp +++ b/source/network/NetSession.cpp @@ -94,6 +94,8 @@ void CNetClientSession::Disconnect(u32 reason) void CNetClientSession::Poll() { + PROFILE3("net client poll"); + ENSURE(m_Host && m_Server); m_FileTransferer.Poll(); @@ -152,6 +154,8 @@ void CNetClientSession::Poll() void CNetClientSession::Flush() { + PROFILE3("net client flush"); + ENSURE(m_Host && m_Server); enet_host_flush(m_Host); diff --git a/source/network/NetTurnManager.cpp b/source/network/NetTurnManager.cpp index dddedde8dd..e80ae743a7 100644 --- a/source/network/NetTurnManager.cpp +++ b/source/network/NetTurnManager.cpp @@ -149,7 +149,7 @@ bool CNetTurnManager::Update(float frameLength, size_t maxTurns) // Save the current state for rewinding, if enabled if (m_TimeWarpNumTurns && (m_CurrentTurn % m_TimeWarpNumTurns) == 0) { - PROFILE("time warp serialization"); + PROFILE3("time warp serialization"); std::stringstream stream; m_Simulation2.SerializeState(stream); m_TimeWarpStates.push_back(stream.str()); @@ -390,7 +390,7 @@ void CNetClientTurnManager::NotifyFinishedUpdate(u32 turn) bool quick = !TurnNeedsFullHash(turn); std::string hash; { - PROFILE("state hash check"); + PROFILE3("state hash check"); bool ok = m_Simulation2.ComputeStateHash(hash, quick); ENSURE(ok); } @@ -435,7 +435,7 @@ void CNetLocalTurnManager::NotifyFinishedUpdate(u32 UNUSED(turn)) #if 0 // this hurts performance and is only useful for verifying log replays std::string hash; { - PROFILE("state hash check"); + PROFILE3("state hash check"); bool ok = m_Simulation2.ComputeStateHash(hash); ENSURE(ok); } diff --git a/source/ps/CConsole.cpp b/source/ps/CConsole.cpp index 3e6ef200da..b4a338de34 100644 --- a/source/ps/CConsole.cpp +++ b/source/ps/CConsole.cpp @@ -175,6 +175,8 @@ void CConsole::Render() { if (! (m_bVisible || m_bToggle) ) return; + PROFILE3("render console"); + CFont font(CONSOLE_FONT); font.Bind(); diff --git a/source/ps/CLogger.cpp b/source/ps/CLogger.cpp index b5ed7ee917..f9747425e0 100644 --- a/source/ps/CLogger.cpp +++ b/source/ps/CLogger.cpp @@ -26,6 +26,7 @@ #include "lib/res/graphics/unifont.h" #include "lib/sysdep/sysdep.h" #include "ps/Font.h" +#include "ps/Profile.h" #include #include @@ -276,6 +277,8 @@ void CLogger::LogError(const wchar_t* fmt, ...) void CLogger::Render() { + PROFILE3("render logger"); + CleanupRenderQueue(); CFont font(L"mono-stroke-10"); diff --git a/source/ps/Filesystem.cpp b/source/ps/Filesystem.cpp index c2968984c5..60a9ca01f7 100644 --- a/source/ps/Filesystem.cpp +++ b/source/ps/Filesystem.cpp @@ -20,6 +20,7 @@ #include "gui/GUIManager.h" #include "ps/CLogger.h" +#include "ps/Profile.h" #include "lib/res/h_mgr.h" // h_reload #include "lib/sysdep/dir_watch.h" @@ -67,6 +68,8 @@ static bool CanIgnore(const DirWatchNotification& notification) Status ReloadChangedFiles() { + PROFILE3("hotload"); + std::vector notifications; RETURN_STATUS_IF_ERR(dir_watch_Poll(notifications)); for(size_t i = 0; i < notifications.size(); i++) diff --git a/source/ps/Game.cpp b/source/ps/Game.cpp index 6307ace09d..d9ad8aa388 100644 --- a/source/ps/Game.cpp +++ b/source/ps/Game.cpp @@ -273,7 +273,6 @@ bool CGame::Update(double deltaTime, bool doInterpolate) // so just use the sim rate itself as the number of turns per frame. size_t maxTurns = (size_t)m_SimRate; - PROFILE("simulation update"); if (m_TurnManager->Update(deltaTime, maxTurns)) { g_GUI->SendEventToAll("SimulationUpdate"); @@ -283,7 +282,6 @@ bool CGame::Update(double deltaTime, bool doInterpolate) if (doInterpolate) { - PROFILE("interpolate"); m_TurnManager->Interpolate(deltaTime); } diff --git a/source/ps/GameSetup/GameSetup.cpp b/source/ps/GameSetup/GameSetup.cpp index 791b1bd392..a9175709fd 100644 --- a/source/ps/GameSetup/GameSetup.cpp +++ b/source/ps/GameSetup/GameSetup.cpp @@ -47,6 +47,7 @@ #include "ps/Overlay.h" #include "ps/Profile.h" #include "ps/ProfileViewer.h" +#include "ps/Profiler2.h" #include "ps/UserReport.h" #include "ps/Util.h" #include "ps/VideoMode.h" @@ -193,6 +194,8 @@ void GUI_DisplayLoadProgress(int percent, const wchar_t* pending_task) void Render() { + PROFILE3("render"); + ogl_WarnIfError(); CStr skystring = "255 0 255"; @@ -235,10 +238,8 @@ void Render() g_Renderer.RenderTextOverlays(); - // Temp GUI message GeeTODO - PROFILE_START("render gui"); - if(g_DoRenderGui) g_GUI->Draw(); - PROFILE_END("render gui"); + if (g_DoRenderGui) + g_GUI->Draw(); ogl_WarnIfError(); @@ -253,30 +254,25 @@ void Render() glLoadIdentity(); - PROFILE_START("render console"); g_Console->Render(); - PROFILE_END("render console"); ogl_WarnIfError(); - PROFILE_START("render logger"); - if(g_DoRenderLogger) g_Logger->Render(); - PROFILE_END("render logger"); + if (g_DoRenderLogger) + g_Logger->Render(); ogl_WarnIfError(); // Profile information - PROFILE_START("render profiling"); g_ProfileViewer.RenderProfile(); - PROFILE_END("render profiling"); ogl_WarnIfError(); // Draw the cursor (or set the Windows cursor, on Windows) if (g_DoRenderCursor) { - PROFILE("render cursor"); + PROFILE3("render cursor"); CStrW cursorName = g_CursorName; if (cursorName.empty()) { @@ -298,6 +294,14 @@ void Render() g_Renderer.EndFrame(); + PROFILE2_ATTR("draw calls: %d", (int)g_Renderer.GetStats().m_DrawCalls); + PROFILE2_ATTR("terrain tris: %d", (int)g_Renderer.GetStats().m_TerrainTris); + PROFILE2_ATTR("water tris: %d", (int)g_Renderer.GetStats().m_WaterTris); + PROFILE2_ATTR("model tris: %d", (int)g_Renderer.GetStats().m_ModelTris); + PROFILE2_ATTR("overlay tris: %d", (int)g_Renderer.GetStats().m_OverlayTris); + PROFILE2_ATTR("blend splats: %d", (int)g_Renderer.GetStats().m_BlendSplats); + PROFILE2_ATTR("particles: %d", (int)g_Renderer.GetStats().m_Particles); + ogl_WarnIfError(); } @@ -694,6 +698,8 @@ void Shutdown(int UNUSED(flags)) wmi_Shutdown(); TIMER_END(L"shutdown wmi"); #endif + + g_Profiler2.Shutdown(); } #if OS_UNIX @@ -773,6 +779,10 @@ void EarlyInit() timer_LatchStartTime(); + // initialise profiler early so it can profile startup + g_Profiler2.Initialise(); + g_Profiler2.RegisterCurrentThread("main"); + FixLocales(); // Because we do GL calls from a secondary thread, Xlib needs to @@ -844,6 +854,8 @@ void Init(const CmdLineArgs& args, int UNUSED(flags)) if (!g_Quickstart) g_UserReporter.Initialize(); // after config + + PROFILE2_EVENT("Init finished"); } void InitGraphics(const CmdLineArgs& args, int flags) diff --git a/source/ps/Profile.h b/source/ps/Profile.h index 8ee102806e..9c32d4f719 100644 --- a/source/ps/Profile.h +++ b/source/ps/Profile.h @@ -25,6 +25,7 @@ #include #include "lib/adts/ring_buf.h" +#include "ps/Profiler2.h" #include "ps/Singleton.h" #include "ps/ThreadUtil.h" @@ -146,14 +147,14 @@ public: class CProfileSample { public: - CProfileSample( const char* name ) + CProfileSample(const char* name) { if (CProfileManager::IsInitialised()) { // The profiler is only safe to use on the main thread ENSURE(ThreadUtil::IsMainThread()); - g_Profiler.Start( name ); + g_Profiler.Start(name); } } ~CProfileSample() @@ -187,11 +188,14 @@ public: } }; -// Put a PROFILE( xyz ) block at the start of all code to be profiled. +// Put a PROFILE("xyz") block at the start of all code to be profiled. // Profile blocks last until the end of the containing scope. -#define PROFILE( name ) CProfileSample __profile( name ) +#define PROFILE(name) CProfileSample __profile(name) // Cheat a bit to make things slightly easier on the user -#define PROFILE_START( name ) { CProfileSample __profile( name ) -#define PROFILE_END( name ) } +#define PROFILE_START(name) { CProfileSample __profile(name) +#define PROFILE_END(name) } + +// Do both old and new profilers simultaneously (1+2=3), for convenience. +#define PROFILE3(name) PROFILE(name); PROFILE2(name) #endif // INCLUDED_PROFILE diff --git a/source/ps/ProfileViewer.cpp b/source/ps/ProfileViewer.cpp index fb22a8e46a..407e30f0ab 100644 --- a/source/ps/ProfileViewer.cpp +++ b/source/ps/ProfileViewer.cpp @@ -159,6 +159,8 @@ void CProfileViewer::RenderProfile() return; } + PROFILE3("render profiler"); + glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); diff --git a/source/ps/ThreadUtil.h b/source/ps/ThreadUtil.h index aa00ae27be..d4e853ad0b 100644 --- a/source/ps/ThreadUtil.h +++ b/source/ps/ThreadUtil.h @@ -19,7 +19,6 @@ #define INCLUDED_THREADUTIL #include "lib/posix/posix_pthread.h" -#include "lib/posix/posix_filesystem.h" // O_CREAT #ifdef DEBUG_LOCKS diff --git a/source/renderer/OverlayRenderer.cpp b/source/renderer/OverlayRenderer.cpp index a8cd900a00..4afbc7970b 100644 --- a/source/renderer/OverlayRenderer.cpp +++ b/source/renderer/OverlayRenderer.cpp @@ -116,7 +116,7 @@ void OverlayRenderer::EndFrame() void OverlayRenderer::PrepareForRendering() { - PROFILE("prepare overlays"); + PROFILE3("prepare overlays"); // This is where we should do something like sort the overlays by // colour/sprite/etc for more efficient rendering @@ -138,7 +138,7 @@ void OverlayRenderer::PrepareForRendering() void OverlayRenderer::RenderOverlaysBeforeWater() { - PROFILE("render overlays (before water)"); + PROFILE3("render overlays (before)"); glDisable(GL_TEXTURE_2D); glEnable(GL_BLEND); @@ -166,7 +166,7 @@ void OverlayRenderer::RenderOverlaysBeforeWater() void OverlayRenderer::RenderOverlaysAfterWater() { - PROFILE("render overlays (after water)"); + PROFILE3("render overlays (after)"); if (!m->texlines.empty()) { @@ -262,7 +262,7 @@ void OverlayRenderer::RenderOverlaysAfterWater() void OverlayRenderer::RenderForegroundOverlays(const CCamera& viewCamera) { - PROFILE("render overlays (fg)"); + PROFILE3("render overlays (fg)"); glEnable(GL_TEXTURE_2D); glEnable(GL_BLEND); diff --git a/source/renderer/ParticleRenderer.cpp b/source/renderer/ParticleRenderer.cpp index aa817b8351..84e46337cd 100644 --- a/source/renderer/ParticleRenderer.cpp +++ b/source/renderer/ParticleRenderer.cpp @@ -76,6 +76,8 @@ struct SortEmitterDistance void ParticleRenderer::PrepareForRendering() { + PROFILE3("prepare particles"); + // Can't load the shader in the constructor because it's called before the // renderer initialisation is complete, so load it the first time through here if (!m->shader) diff --git a/source/renderer/PatchRData.cpp b/source/renderer/PatchRData.cpp index 5f9b5dc711..2354816b57 100644 --- a/source/renderer/PatchRData.cpp +++ b/source/renderer/PatchRData.cpp @@ -146,6 +146,8 @@ struct SBlendLayer void CPatchRData::BuildBlends() { + PROFILE3("build blends"); + m_BlendSplats.clear(); std::vector blendVertices; @@ -428,6 +430,8 @@ void CPatchRData::AddBlend(std::vector& blendVertices, std::vector void CPatchRData::BuildIndices() { + PROFILE3("build indices"); + CTerrain* terrain = m_Patch->m_Parent; ssize_t px = m_Patch->m_X * PATCH_SIZE; @@ -520,6 +524,8 @@ void CPatchRData::BuildIndices() void CPatchRData::BuildVertices() { + PROFILE3("build vertices"); + // create both vertices and lighting colors // number of vertices in each direction in each patch @@ -613,6 +619,8 @@ void CPatchRData::BuildSide(std::vector& vertices, CPatchSideFlags void CPatchRData::BuildSides() { + PROFILE3("build sides"); + std::vector sideVertices; int sideFlags = m_Patch->GetSideFlags(); @@ -1142,6 +1150,8 @@ void CPatchRData::RenderPriorities() // Build vertex buffer for water vertices over our patch void CPatchRData::BuildWater() { + PROFILE3("build water"); + // number of vertices in each direction in each patch ENSURE((PATCH_SIZE % water_cell_size) == 0); diff --git a/source/renderer/Renderer.cpp b/source/renderer/Renderer.cpp index b8308bc18f..739bf4a73a 100644 --- a/source/renderer/Renderer.cpp +++ b/source/renderer/Renderer.cpp @@ -933,7 +933,7 @@ void CRenderer::SetClearColor(SColor4ub color) void CRenderer::RenderShadowMap() { - PROFILE("render shadow map"); + PROFILE3("render shadow map"); m->shadow->BeginRender(); @@ -978,7 +978,7 @@ void CRenderer::RenderShadowMap() void CRenderer::RenderPatches(const CFrustum* frustum) { - PROFILE("render patches"); + PROFILE3("render patches"); bool filtered = false; if (frustum) @@ -1050,7 +1050,7 @@ private: void CRenderer::RenderModels(const CFrustum* frustum) { - PROFILE("render models"); + PROFILE3("render models"); int flags = 0; if (frustum) @@ -1087,7 +1087,7 @@ void CRenderer::RenderModels(const CFrustum* frustum) void CRenderer::RenderTransparentModels(ETransparentMode transparentMode, const CFrustum* frustum) { - PROFILE("render transparent models"); + PROFILE3("render transparent models"); int flags = 0; if (frustum) @@ -1360,7 +1360,7 @@ SScreenRect CRenderer::RenderRefractions(const CBound &scissor) void CRenderer::RenderSilhouettes() { - PROFILE("render silhouettes"); + PROFILE3("render silhouettes"); // Render silhouettes of units hidden behind terrain or occluders. // To avoid breaking the standard rendering of alpha-blended objects, this @@ -1473,7 +1473,7 @@ void CRenderer::RenderParticles() if (GetRenderPath() != RP_SHADER) return; - PROFILE("render particles"); + PROFILE3("render particles"); m->particleRenderer.RenderParticles(); @@ -1499,7 +1499,7 @@ void CRenderer::RenderParticles() // RenderSubmissions: force rendering of any batched objects void CRenderer::RenderSubmissions() { - PROFILE("render submissions"); + PROFILE3("render submissions"); ogl_WarnIfError(); @@ -1507,7 +1507,8 @@ void CRenderer::RenderSubmissions() m->SetOpenGLCamera(m_ViewCamera); // Prepare model renderers - PROFILE_START("prepare models"); + { + PROFILE3("prepare models"); m->Model.Normal->PrepareModels(); m->Model.Player->PrepareModels(); if (m->Model.Normal != m->Model.NormalInstancing) @@ -1515,19 +1516,13 @@ void CRenderer::RenderSubmissions() if (m->Model.Player != m->Model.PlayerInstancing) m->Model.PlayerInstancing->PrepareModels(); m->Model.Transp->PrepareModels(); - PROFILE_END("prepare models"); + } - PROFILE_START("prepare terrain"); m->terrainRenderer->PrepareForRendering(); - PROFILE_END("prepare terrain"); - PROFILE_START("prepare overlays"); m->overlayRenderer.PrepareForRendering(); - PROFILE_END("prepare overlays"); - PROFILE_START("prepare particles"); m->particleRenderer.PrepareForRendering(); - PROFILE_END("prepare particles"); if (m_Caps.m_Shadows && m_Options.m_Shadows && GetRenderPath() == RP_SHADER) { @@ -1639,7 +1634,7 @@ void CRenderer::RenderSubmissions() // EndFrame: signal frame end void CRenderer::EndFrame() { - PROFILE("end frame"); + PROFILE3("end frame"); // empty lists m->terrainRenderer->EndFrame(); @@ -1657,9 +1652,12 @@ void CRenderer::EndFrame() ogl_tex_bind(0, 0); - if (glGetError()) { - ONCE(LOGERROR(L"CRenderer::EndFrame: GL errors occurred")); + PROFILE3("error check"); + if (glGetError()) + { + ONCE(LOGERROR(L"CRenderer::EndFrame: GL errors occurred")); + } } } diff --git a/source/renderer/TerrainOverlay.cpp b/source/renderer/TerrainOverlay.cpp index f598d42c4a..84e1a40bd0 100644 --- a/source/renderer/TerrainOverlay.cpp +++ b/source/renderer/TerrainOverlay.cpp @@ -93,7 +93,7 @@ void TerrainOverlay::RenderOverlays() if (g_TerrainOverlayList.size() == 0) return; - PROFILE("render terrain overlays"); + PROFILE3("render terrain overlays"); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); diff --git a/source/renderer/TerrainRenderer.cpp b/source/renderer/TerrainRenderer.cpp index 13b71bccf2..475635668d 100644 --- a/source/renderer/TerrainRenderer.cpp +++ b/source/renderer/TerrainRenderer.cpp @@ -610,7 +610,7 @@ CBound TerrainRenderer::ScissorWater(const CMatrix3D &viewproj) // Render fancy water bool TerrainRenderer::RenderFancyWater() { - PROFILE("render fancy water"); + PROFILE3("render fancy water"); // If we're using fancy water, make sure its shader is loaded if (!m->fancyWaterShader) @@ -739,7 +739,7 @@ bool TerrainRenderer::RenderFancyWater() void TerrainRenderer::RenderSimpleWater() { - PROFILE("render simple water"); + PROFILE3("render simple water"); WaterManager* WaterMgr = g_Renderer.GetWaterManager(); CLOSTexture& losTexture = g_Game->GetView()->GetLOSTexture(); diff --git a/source/simulation2/Simulation2.cpp b/source/simulation2/Simulation2.cpp index c56f30f069..4aca8fa4f2 100644 --- a/source/simulation2/Simulation2.cpp +++ b/source/simulation2/Simulation2.cpp @@ -324,6 +324,9 @@ void CSimulation2Impl::ReportSerializationFailure( void CSimulation2Impl::Update(int turnLength, const std::vector& commands) { + PROFILE3("sim update"); + PROFILE2_ATTR("turn %d", (int)m_TurnNumber); + fixed turnLengthFixed = fixed::FromInt(turnLength) / 1000; /* @@ -510,6 +513,8 @@ void CSimulation2Impl::UpdateComponents(CSimContext& simContext, fixed turnLengt void CSimulation2Impl::Interpolate(float frameLength, float frameOffset) { + PROFILE3("sim interpolate"); + m_LastFrameOffset = frameOffset; CMessageInterpolate msg(frameLength, frameOffset); @@ -654,6 +659,8 @@ void CSimulation2::Interpolate(float frameLength, float frameOffset) void CSimulation2::RenderSubmit(SceneCollector& collector, const CFrustum& frustum, bool culling) { + PROFILE3("sim submit"); + CMessageRenderSubmit msg(collector, frustum, culling); m->m_ComponentManager.BroadcastMessage(msg); } diff --git a/source/simulation2/components/CCmpAIManager.cpp b/source/simulation2/components/CCmpAIManager.cpp index c222bac993..f16e006365 100644 --- a/source/simulation2/components/CCmpAIManager.cpp +++ b/source/simulation2/components/CCmpAIManager.cpp @@ -440,7 +440,7 @@ private: // Deserialize the game state, to pass to the AI's HandleMessage CScriptVal state; { - PROFILE("AI compute read state"); + PROFILE3("AI compute read state"); state = m_ScriptInterface.ReadStructuredClone(m_GameState); m_ScriptInterface.SetProperty(state.get(), "passabilityMap", m_PassabilityMapVal, true); m_ScriptInterface.SetProperty(state.get(), "territoryMap", m_TerritoryMapVal, true); @@ -452,10 +452,12 @@ private: // affecting other AI scripts they share it with. But the performance // cost is far too high, so we won't do that. + for (size_t i = 0; i < m_Players.size(); ++i) { - PROFILE("AI compute scripts"); - for (size_t i = 0; i < m_Players.size(); ++i) - m_Players[i]->Run(state); + PROFILE3("AI script"); + PROFILE2_ATTR("player: %d", m_Players[i]->m_Player); + PROFILE2_ATTR("script: %ls", m_Players[i]->m_AIName.c_str()); + m_Players[i]->Run(state); } // Run the GC every so often. @@ -463,7 +465,7 @@ private: // since it avoids random GC delays while running other scripts) if (m_TurnNum++ % 25 == 0) { - PROFILE("AI compute GC"); + PROFILE3("AI compute GC"); m_ScriptInterface.MaybeGC(); } } diff --git a/source/simulation2/components/CCmpRangeManager.cpp b/source/simulation2/components/CCmpRangeManager.cpp index b01dd110bb..68dff4613a 100644 --- a/source/simulation2/components/CCmpRangeManager.cpp +++ b/source/simulation2/components/CCmpRangeManager.cpp @@ -649,7 +649,7 @@ public: */ void ExecuteActiveQueries() { - PROFILE("ExecuteActiveQueries"); + PROFILE3("ExecuteActiveQueries"); // Store a queue of all messages before sending any, so we can assume // no entities will move until we've finished checking all the ranges diff --git a/source/tools/atlas/GameInterface/MessagePasserImpl.cpp b/source/tools/atlas/GameInterface/MessagePasserImpl.cpp index 9ea2df6629..9f9e04b071 100644 --- a/source/tools/atlas/GameInterface/MessagePasserImpl.cpp +++ b/source/tools/atlas/GameInterface/MessagePasserImpl.cpp @@ -24,6 +24,7 @@ #include "lib/timer.h" #include "lib/rand.h" +#include "lib/posix/posix_filesystem.h" using namespace AtlasMessage;