LCOV - code coverage report
Current view: top level - engine/render - rendertimers.cpp (source / functions) Coverage Total Hit
Test: Libprimis Test Coverage Lines: 0.0 % 83 0
Test Date: 2025-02-21 06:59:27 Functions: 0.0 % 7 0

            Line data    Source code
       1              : /* rendertimers.cpp: renderer functionality used for displaying rendering stats
       2              :  * while the program is running
       3              :  *
       4              :  * timers can be created with designated start/stop points in the code; sub-ms
       5              :  * times needed for accurate diagnosis possible (each frame is ~16.6ms @ 60Hz)
       6              :  *
       7              :  * used in rendergl.cpp
       8              :  */
       9              : #include "../libprimis-headers/cube.h"
      10              : #include "../../shared/geomexts.h"
      11              : #include "../../shared/glexts.h"
      12              : 
      13              : #include "rendergl.h"
      14              : #include "rendertext.h"
      15              : #include "renderttf.h"
      16              : #include "renderva.h"
      17              : 
      18              : #include "interface/control.h"
      19              : 
      20              : void cleanuptimers();                              //needed for timer script gvar
      21            0 : VARFN(timer, usetimers, 0, 0, 1, cleanuptimers()); //toggles logging timer information & rendering it
      22              : VAR(frametimer, 0, 0, 1);                          //toggles timing how long each frame takes (and rendering it to timer ui)
      23              : 
      24              : struct timer
      25              : {
      26              :     enum
      27              :     {
      28              :         Timer_MaxQuery = 4          //max number of gl queries
      29              :     };
      30              :     const char *name;               //name the timer reports as
      31              :     bool gpu;                       //whether the timer is for gpu time (true) or cpu time
      32              :     std::array<GLuint, Timer_MaxQuery> query; //gpu query information
      33              :     int waiting;                    //internal bitmask for queries
      34              :     uint starttime;                 //time the timer was started (in terms of ms since game started)
      35              :     float result,                   //raw value of the timer, -1 if no info available
      36              :           print;                    //the time the timer displays: ms per frame for whatever object
      37              : };
      38              : 
      39              : //locally relevant functionality
      40              : namespace
      41              : {
      42              :     std::vector<timer> timers;
      43              :     std::vector<uint> timerorder;
      44              :     uint timercycle = 0;
      45              : 
      46            0 :     timer *findtimer(const char *name, bool gpu) //also creates a new timer if none found
      47              :     {
      48            0 :         for(uint i = 0; i < timers.size(); i++)
      49              :         {
      50            0 :             if(!std::strcmp(timers[i].name, name) && timers[i].gpu == gpu)
      51              :             {
      52            0 :                 timerorder.erase(std::find(timerorder.begin(), timerorder.end(), i));
      53            0 :                 timerorder.push_back(i);
      54            0 :                 return &timers[i];
      55              :             }
      56              :         }
      57            0 :         timerorder.push_back(timers.size());
      58            0 :         timers.emplace_back();
      59            0 :         timer &t = timers.back();
      60            0 :         t.name = name;
      61            0 :         t.gpu = gpu;
      62            0 :         t.query.fill(0);
      63            0 :         if(gpu)
      64              :         {
      65            0 :             glGenQueries(timer::Timer_MaxQuery, t.query.data());
      66              :         }
      67            0 :         t.waiting = 0;
      68            0 :         t.starttime = 0;
      69            0 :         t.result = -1;
      70            0 :         t.print = -1;
      71            0 :         return &t;
      72              :     }
      73              : }
      74              : 
      75              : //externally relevant functionality
      76              : 
      77              : //used to start a timer in some part of the code, cannot be used outside of rendering part
      78              : /**
      79              :  * @brief activates a timer that starts its query from a given point in the code
      80              :  *
      81              :  * Creates a new timer if necessary.
      82              :  *
      83              :  * @param name The name of the timer to use
      84              :  * @param gpu Toggles timing GPU rendering time
      85              :  *
      86              :  * @return a pointer to the relevant timer
      87              :  */
      88            0 : timer *begintimer(const char *name, bool gpu)
      89              : {
      90            0 :     if(!usetimers || inbetweenframes || (gpu && (!hasTQ || deferquery)))
      91              :     {
      92            0 :         return nullptr;
      93              :     }
      94            0 :     timer *t = findtimer(name, gpu);
      95            0 :     if(t->gpu)
      96              :     {
      97            0 :         deferquery++;
      98            0 :         glBeginQuery(GL_TIME_ELAPSED_EXT, t->query[timercycle]);
      99            0 :         t->waiting |= 1<<timercycle;
     100              :     }
     101              :     else
     102              :     {
     103            0 :         t->starttime = getclockmillis();
     104              :     }
     105            0 :     return t;
     106              : }
     107              : 
     108              : //used to end a timer started by begintimer(), needs to be included sometime after begintimer
     109              : //the part between begintimer() and endtimer() is what gets timed
     110            0 : void endtimer(timer *t)
     111              : {
     112            0 :     if(!t)
     113              :     {
     114            0 :         return;
     115              :     }
     116            0 :     if(t->gpu)
     117              :     {
     118            0 :         glEndQuery(GL_TIME_ELAPSED_EXT);
     119            0 :         deferquery--;
     120              :     }
     121              :     else
     122              :     {
     123            0 :         t->result = std::max(static_cast<float>(getclockmillis() - t->starttime), 0.0f);
     124              :     }
     125              : }
     126              : 
     127              : //foreach timer, query what time has passed since last update
     128            0 : void synctimers()
     129              : {
     130            0 :     timercycle = (timercycle + 1) % timer::Timer_MaxQuery;
     131              : 
     132            0 :     for(timer& t : timers)
     133              :     {
     134            0 :         if(t.waiting&(1<<timercycle))
     135              :         {
     136            0 :             GLint available = 0;
     137            0 :             while(!available)
     138              :             {
     139            0 :                 glGetQueryObjectiv(t.query[timercycle], GL_QUERY_RESULT_AVAILABLE, &available);
     140              :             }
     141            0 :             GLuint64EXT result = 0;
     142            0 :             glGetQueryObjectui64v(t.query[timercycle], GL_QUERY_RESULT, &result);
     143            0 :             t.result = std::max(static_cast<float>(result) * 1e-6f, 0.0f);
     144            0 :             t.waiting &= ~(1<<timercycle);
     145              :         }
     146              :         else
     147              :         {
     148            0 :             t.result = -1;
     149              :         }
     150              :     }
     151            0 : }
     152              : 
     153              : /**
     154              :  * @brief deletes the elements in the timers global vector
     155              :  *
     156              :  * Deletes the elements in the `timer` global variable. If any GPU queries are active,
     157              :  * they are cancelled so as not to waste the GPU's time
     158              :  */
     159            0 : void cleanuptimers()
     160              : {
     161            0 :     for(const timer& t : timers)
     162              :     {
     163            0 :         if(t.gpu)
     164              :         {
     165            0 :             glDeleteQueries(timer::Timer_MaxQuery, t.query.data());
     166              :         }
     167              :     }
     168            0 :     timers.clear();
     169            0 :     timerorder.clear();
     170            0 : }
     171              : 
     172              : /*
     173              :  * draws timers to the screen using hardcoded text
     174              :  *
     175              :  * if frametimer gvar is enabled, also shows the overall frame time
     176              :  * otherwise, prints out all timer information available
     177              :  */
     178            0 : void printtimers(int conw, int framemillis)
     179              : {
     180            0 :     if(!frametimer && !usetimers)
     181              :     {
     182            0 :         return;
     183              :     }
     184              :     static int lastprint = 0;
     185            0 :     int offset = 0;
     186            0 :     if(frametimer)
     187              :     {
     188              :         static int printmillis = 0;
     189            0 :         if(totalmillis - lastprint >= 200)
     190              :         {
     191            0 :             printmillis = framemillis;
     192              :         }
     193              :         char framestring[200];
     194            0 :         constexpr int size = 42;
     195            0 :         std::sprintf(framestring, "frame time %i ms", printmillis);
     196            0 :         ttr.fontsize(size);
     197            0 :         ttr.renderttf(framestring, {0xFF, 0xFF, 0xFF, 0}, conw-20*size, size*3/2+offset*9*size/8);
     198              :         //draw_textf("frame time %i ms", conw-20*FONTH, conh-FONTH*3/2-offset*9*FONTH/8, printmillis);
     199            0 :         offset++;
     200              :     }
     201            0 :     if(usetimers)
     202              :     {
     203            0 :         for(int i : timerorder)
     204              :         {
     205            0 :             timer &t = timers[i];
     206            0 :             if(t.print < 0 ? t.result >= 0 : totalmillis - lastprint >= 200)
     207              :             {
     208            0 :                 t.print = t.result;
     209              :             }
     210            0 :             if(t.print < 0 || (t.gpu && !(t.waiting&(1<<timercycle))))
     211              :             {
     212            0 :                 continue;
     213              :             }
     214              :             char framestring[200];
     215            0 :             constexpr int size = 42;
     216            0 :             std::sprintf(framestring, "%s%s %5.2f ms", t.name, t.gpu ? "" : " (cpu)", t.print);
     217            0 :             ttr.fontsize(size);
     218            0 :             ttr.renderttf(framestring, {0xFF, 0xFF, 0xFF, 0}, conw-20*size, size*3/2+offset*9*size/8);
     219              : 
     220              :             //draw_textf("%s%s %5.2f ms", conw-20*FONTH, conh-FONTH*3/2-offset*9*FONTH/8, t.name, t.gpu ? "" : " (cpu)", t.print);
     221            0 :             offset++;
     222              :         }
     223              :     }
     224            0 :     if(totalmillis - lastprint >= 200)
     225              :     {
     226            0 :         lastprint = totalmillis;
     227              :     }
     228              : }
        

Generated by: LCOV version 2.0-1