From d8e15c7dbfcaf848ae7db165289b7ee9c687133c Mon Sep 17 00:00:00 2001 From: Ketmar Dark Date: Thu, 17 Aug 2017 12:41:28 +0300 Subject: [PATCH] more profiler code; smoothing values, history --- src/game/g_game.pas | 134 ++++++++++++++++++++++++--------------- src/shared/xprofiler.pas | 133 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 217 insertions(+), 50 deletions(-) diff --git a/src/game/g_game.pas b/src/game/g_game.pas index bfdea2d..14819e2 100644 --- a/src/game/g_game.pas +++ b/src/game/g_game.pas @@ -329,6 +329,11 @@ uses utils, sfs; +// ////////////////////////////////////////////////////////////////////////// // +var + profileFrameDraw: TProfiler = nil; + + // ////////////////////////////////////////////////////////////////////////// // type TDynLight = record @@ -405,7 +410,8 @@ end; // ////////////////////////////////////////////////////////////////////////// // -procedure drawProfiles (x, y: Integer; title: AnsiString); +(* +procedure drawProfiles (x, y: Integer; title: AnsiString); overload; var wdt, hgt: Integer; yy: Integer; @@ -439,7 +445,8 @@ var begin // gScreenWidth - if not xprofItReset() then exit; + //if not xprofItReset() then exit; + if (xprofTotalCount = 0) then exit; wdt := 256; hgt := 16+2+xprofTotalCount*(16+2); // title, items // background @@ -450,6 +457,33 @@ begin yy := y+16+2; drawItems(); end; +*) + + +procedure drawProfiles (x, y: Integer; prof: TProfiler); +var + wdt, hgt: Integer; + yy: Integer; + ii, idx: Integer; +begin + if (prof = nil) then exit; + // gScreenWidth + if (length(prof.bars) = 0) then exit; + wdt := 192; + hgt := length(prof.bars)*(16+2); + if (x < 0) then x := gScreenWidth-(wdt-1)+x; + if (y < 0) then y := gScreenHeight-(hgt-1)+y; + // background + //e_DrawFillQuad(x, y, x+wdt-1, y+hgt-1, 255, 255, 255, 200, B_BLEND); + e_DrawFillQuad(x, y, x+wdt-1, y+hgt-1, 20, 20, 20, 0, B_NONE); + // title + yy := y+2; + for ii := 0 to High(prof.bars) do + begin + e_TextureFontPrintEx(x+2+4*prof.bars[ii].level, yy, Format('%s: %d', [prof.bars[ii].name, prof.bars[ii].value]), gStdFont, 255, 255, 0, 1, false); + Inc(yy, 16+2); + end; +end; // ////////////////////////////////////////////////////////////////////////// // @@ -2703,6 +2737,9 @@ begin Exit; end; + if (profileFrameDraw = nil) then profileFrameDraw := TProfiler.Create('MAP RENDER'); + profileFrameDraw.mainBegin(g_profile_frame_draw); + gPlayerDrawn := p; glPushMatrix(); @@ -2770,9 +2807,9 @@ begin else d := Round((py-p.IncCam-(gPlayerScreenSize.Y div 2))/(gMapInfo.Height-gPlayerScreenSize.Y)*(gBackSize.Y-gPlayerScreenSize.Y)); - xprofBeginSection('map background'); + profileFrameDraw.sectionBegin('map background'); g_Map_DrawBack(-c, -d); - xprofEndSection(); + profileFrameDraw.sectionEnd(); sX := -a; sY := -(b+p.IncCam); @@ -2781,73 +2818,73 @@ begin glTranslatef(a, b+p.IncCam, 0); - xprofBeginSection('map rendering'); + profileFrameDraw.sectionBegin('map rendering'); - xprofBeginSection('panel_back'); + profileFrameDraw.sectionBegin('panel_back'); g_Map_DrawPanels(sX, sY, sWidth, sHeight, PANEL_BACK); - xprofEndSection(); + profileFrameDraw.sectionEnd(); - xprofBeginSection('panel_step'); + profileFrameDraw.sectionBegin('panel_step'); g_Map_DrawPanels(sX, sY, sWidth, sHeight, PANEL_STEP); - xprofEndSection(); + profileFrameDraw.sectionEnd(); - xprofBeginSection('items'); + profileFrameDraw.sectionBegin('items'); g_Items_Draw(); - xprofEndSection(); + profileFrameDraw.sectionEnd(); - xprofBeginSection('weapons'); + profileFrameDraw.sectionBegin('weapons'); g_Weapon_Draw(); - xprofEndSection(); + profileFrameDraw.sectionEnd(); - xprofBeginSection('shells'); + profileFrameDraw.sectionBegin('shells'); g_Player_DrawShells(); - xprofEndSection(); + profileFrameDraw.sectionEnd(); - xprofBeginSection('drawall'); + profileFrameDraw.sectionBegin('drawall'); g_Player_DrawAll(); - xprofEndSection(); + profileFrameDraw.sectionEnd(); - xprofBeginSection('corpses'); + profileFrameDraw.sectionBegin('corpses'); g_Player_DrawCorpses(); - xprofEndSection(); + profileFrameDraw.sectionEnd(); - xprofBeginSection('panel_wall'); + profileFrameDraw.sectionBegin('panel_wall'); g_Map_DrawPanels(sX, sY, sWidth, sHeight, PANEL_WALL); - xprofEndSection(); + profileFrameDraw.sectionEnd(); - xprofBeginSection('monsters'); + profileFrameDraw.sectionBegin('monsters'); g_Monsters_Draw(); - xprofEndSection(); + profileFrameDraw.sectionEnd(); - xprofBeginSection('panel_closedoor'); + profileFrameDraw.sectionBegin('panel_closedoor'); g_Map_DrawPanels(sX, sY, sWidth, sHeight, PANEL_CLOSEDOOR); - xprofEndSection(); + profileFrameDraw.sectionEnd(); - xprofBeginSection('gfx'); + profileFrameDraw.sectionBegin('gfx'); g_GFX_Draw(); - xprofEndSection(); + profileFrameDraw.sectionEnd(); - xprofBeginSection('flags'); + profileFrameDraw.sectionBegin('flags'); g_Map_DrawFlags(); - xprofEndSection(); + profileFrameDraw.sectionEnd(); - xprofBeginSection('panel_acid1'); + profileFrameDraw.sectionBegin('panel_acid1'); g_Map_DrawPanels(sX, sY, sWidth, sHeight, PANEL_ACID1); - xprofEndSection(); + profileFrameDraw.sectionEnd(); - xprofBeginSection('panel_acid2'); + profileFrameDraw.sectionBegin('panel_acid2'); g_Map_DrawPanels(sX, sY, sWidth, sHeight, PANEL_ACID2); - xprofEndSection(); + profileFrameDraw.sectionEnd(); - xprofBeginSection('panel_water'); + profileFrameDraw.sectionBegin('panel_water'); g_Map_DrawPanels(sX, sY, sWidth, sHeight, PANEL_WATER); - xprofEndSection(); + profileFrameDraw.sectionEnd(); //TODO: lights should be in separate grid, i think // but on the other side: grid may be slower for dynlights, as their lifetime is short if gwin_has_stencil and (g_dynLightCount > 0) then begin - xprofBeginSection('dynlights'); + profileFrameDraw.sectionBegin('dynlights'); // setup OpenGL parameters glStencilMask($FFFFFFFF); @@ -2902,27 +2939,27 @@ begin glDisable(GL_SCISSOR_TEST); glScissor(0, 0, sWidth, sHeight); - xprofEndSection(); + profileFrameDraw.sectionEnd(); end else begin - xprofBeginSection('dynlights'); - xprofEndSection(); + profileFrameDraw.sectionBegin('dynlights'); + profileFrameDraw.sectionEnd(); end; - xprofBeginSection('panel_fore'); + profileFrameDraw.sectionBegin('panel_fore'); g_Map_DrawPanels(sX, sY, sWidth, sHeight, PANEL_FORE); - xprofEndSection(); + profileFrameDraw.sectionEnd(); if g_debug_HealthBar then begin - xprofBeginSection('monster health'); + profileFrameDraw.sectionBegin('monster health'); g_Monsters_DrawHealth(); - xprofEndSection(); + profileFrameDraw.sectionEnd(); - xprofBeginSection('player health'); + profileFrameDraw.sectionBegin('player health'); g_Player_DrawHealth(); - xprofEndSection(); + profileFrameDraw.sectionEnd(); end; if p.FSpectator then @@ -2949,7 +2986,7 @@ begin glPopMatrix(); - xprofEndSection(); // map rendering + profileFrameDraw.mainEnd(); // map rendering p.DrawPain(); p.DrawPickup(); @@ -2981,8 +3018,6 @@ begin FPSTime := Time; end; - xprofBegin(g_profile_frame_draw); - if gGameOn or (gState = STATE_FOLD) then begin if (gPlayer1 <> nil) and (gPlayer2 <> nil) then @@ -3284,8 +3319,7 @@ begin Format('%d:%.2d:%.2d', [gTime div 1000 div 3600, (gTime div 1000 div 60) mod 60, gTime div 1000 mod 60]), gStdFont); - xprofEnd(); - if g_profile_frame_draw then drawProfiles(0, 0, 'MAP RENDER'); + if g_profile_frame_draw then drawProfiles(-1, -1, profileFrameDraw); //drawProfiles(-1, -1, 'MAP RENDER'); end; procedure g_Game_Quit(); diff --git a/src/shared/xprofiler.pas b/src/shared/xprofiler.pas index 9b71111..225e9de 100644 --- a/src/shared/xprofiler.pas +++ b/src/shared/xprofiler.pas @@ -84,6 +84,54 @@ type {$ENDIF} +const + TProfHistorySize = 100; + +type + TProfilerBar = record + private + const FilterFadeoff = 0.05; // 5% + + private + history: array [0..TProfHistorySize-1] of Integer; // circular buffer + hisHead: Integer; + curval: Single; + mName: AnsiString; + mLevel: Integer; + + private + procedure initialize (); inline; + function getvalue (): Integer; inline; + function getvalat (idx: Integer): Integer; inline; + function getcount (): Integer; inline; + + public + procedure update (val: Integer); + + property value: Integer read getvalue; + property name: AnsiString read mName; + property level: Integer read mLevel; + property count: Integer read getcount; + property values[idx: Integer]: Integer read getvalat; + end; + + TProfiler = class(TObject) + public + bars: array of TProfilerBar; + name: AnsiString; + + public + constructor Create (aName: AnsiString); + destructor Destroy (); override; + + procedure mainBegin (reallyActivate: Boolean=true); + procedure mainEnd (); + + procedure sectionBegin (name: AnsiString); + procedure sectionEnd (); + end; + + // call this on frame start procedure xprofBegin (reallyActivate: Boolean=true); // call this on frame end @@ -503,6 +551,91 @@ function xprofItPop (): Boolean; begin result := false; end; function xprofItNext (): Boolean; begin result := false; end; {$ENDIF} + +// ////////////////////////////////////////////////////////////////////////// // +procedure TProfilerBar.initialize (); begin hisHead := -1; curval := 0; end; + +procedure TProfilerBar.update (val: Integer); +var + idx: Integer; +begin + if (val < 0) then val := 0; //else if (val > 1000000) val := 1000000; + if (hisHead = -1) then begin hisHead := 0; curval := 0; for idx := 0 to TProfHistorySize-1 do history[idx] := val; end; + history[hisHead] := val; + Inc(hisHead); + if (hisHead = TProfHistorySize) then hisHead := 0; + curval := FilterFadeoff*val+(1.0-FilterFadeoff)*curval; +end; + +function TProfilerBar.getvalue (): Integer; begin result := round(curval); end; + +function TProfilerBar.getcount (): Integer; begin result := TProfHistorySize; end; + +function TProfilerBar.getvalat (idx: Integer): Integer; +begin + if (idx < 0) or (idx >= TProfHistorySize) then result := 0 else result := history[(hisHead-idx-1+TProfHistorySize*2) mod TProfHistorySize]; +end; + + +// ////////////////////////////////////////////////////////////////////////// // +constructor TProfiler.Create (aName: AnsiString); +begin + name := aName; + bars := nil; +end; + + +destructor TProfiler.Destroy (); +begin + bars := nil; + inherited; +end; + + +procedure TProfiler.mainBegin (reallyActivate: Boolean=true); +begin + xprofBegin(reallyActivate); +end; + +procedure TProfiler.mainEnd (); +var + idx: Integer; +begin + xprofEnd(); + if (xprofTotalCount > 0) then + begin + // first time? + if (length(bars) = 0) or (length(bars) <> xprofTotalCount+1) then + begin + //if (length(bars) <> 0) then raise Exception.Create('FUUUUUUUUUUUUUUU'); + SetLength(bars, xprofTotalCount+1); + for idx := 1 to xprofTotalCount do + begin + bars[idx].initialize(); + bars[idx].mName := xprofNameAt(idx-1); + bars[idx].mLevel := xprofLevelAt(idx-1)+1; + end; + bars[0].initialize(); + bars[0].mName := name; + bars[0].mLevel := 0; + end; + // update bars + for idx := 1 to xprofTotalCount do bars[idx].update(xprofMicroAt(idx-1)); + bars[0].update(xprofTotalMicro); + end; +end; + +procedure TProfiler.sectionBegin (name: AnsiString); +begin + xprofBeginSection(name); +end; + +procedure TProfiler.sectionEnd (); +begin + xprofEndSection(); +end; + + begin {$IF DEFINED(STOPWATCH_IS_HERE)} xprofGlobalInit(); -- 2.29.2