Skip to content

Commit

Permalink
Improve fps counter (#1886)
Browse files Browse the repository at this point in the history
  • Loading branch information
GabrielNakamoto authored Jan 12, 2025
1 parent 1fa15c3 commit b134d54
Show file tree
Hide file tree
Showing 5 changed files with 92 additions and 13 deletions.
1 change: 1 addition & 0 deletions vtkext/private/module/Testing/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ set(test_sources
TestF3DOpenGLGridMapper.cxx
TestF3DRenderPass.cxx
TestF3DRendererWithColoring.cxx
TestF3DFpsCounter.cxx
)

if(F3D_MODULE_EXR)
Expand Down
54 changes: 54 additions & 0 deletions vtkext/private/module/Testing/TestF3DFpsCounter.cxx
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
#include <vtkNew.h>
#include <vtkObjectFactory.h>

#include "vtkF3DUIActor.h"

#include <iostream>

// subclass to retrieve internal protected values
class vtkF3DTestUIActor : public vtkF3DUIActor
{
public:
static vtkF3DTestUIActor* New();
vtkTypeMacro(vtkF3DTestUIActor, vtkF3DUIActor);

size_t GetNumberOfFrameTimes() { return this->FrameTimes.size(); }
double GetTotalFrameTimes() { return this->TotalFrameTimes; }
int GetFpsValue() { return this->FpsValue; }
};

vtkObjectFactoryNewMacro(vtkF3DTestUIActor);

int TestF3DFpsCounter(int argc, char* argv[])
{
vtkNew<vtkF3DTestUIActor> uiActor;

// add 1000 frames at 0.01s
for (int i = 0; i < 1000; i++)
{
uiActor->UpdateFpsValue(0.01);
}

// make sure only the 100 last records are kept
if (uiActor->GetNumberOfFrameTimes() > 100)
{
std::cerr << "Number of frame times must be at most 100" << std::endl;
return EXIT_FAILURE;
}

// make sure only the total time kept doesn't exceed 1 second
if (uiActor->GetTotalFrameTimes() > 1.0)
{
std::cerr << "Number of total frame times must be at most 1.0" << std::endl;
return EXIT_FAILURE;
}

// make sure the FPS value is exactly 100
if (uiActor->GetFpsValue() != 100)
{
std::cerr << "Number of FPS value must be exactly 100" << std::endl;
return EXIT_FAILURE;
}

return EXIT_SUCCESS;
}
24 changes: 15 additions & 9 deletions vtkext/private/module/vtkF3DRenderer.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -1552,20 +1552,26 @@ void vtkF3DRenderer::Render()

auto cpuElapsed = std::chrono::high_resolution_clock::now() - cpuStart;

// Get CPU frame per seconds
int fps = static_cast<int>(std::round(
1.0 / (std::chrono::duration_cast<std::chrono::microseconds>(cpuElapsed).count() * 1e-6)));
vtkInformation *info = this->GetInformation();

bool uiOnly = info->Get(vtkF3DRenderPass::RENDER_UI_ONLY());

if (!uiOnly)
{
// Get CPU frame time
double elapsedTime = std::chrono::duration_cast<std::chrono::microseconds>(cpuElapsed).count() * 1e-6;

#if !defined(__ANDROID__) && !defined(__EMSCRIPTEN__)
glEndQuery(GL_TIME_ELAPSED);
GLint elapsed;
glGetQueryObjectiv(this->Timer, GL_QUERY_RESULT, &elapsed);
glEndQuery(GL_TIME_ELAPSED);
GLint elapsed;
glGetQueryObjectiv(this->Timer, GL_QUERY_RESULT, &elapsed);

// Get min between CPU frame per seconds and GPU frame per seconds
fps = std::min(fps, static_cast<int>(std::round(1.0 / (elapsed * 1e-9))));
// Get min between CPU frame time and GPU frame time
elapsedTime = std::min(elapsedTime, elapsed * 1e-9);
#endif

this->UIActor->SetFpsValue(fps);
this->UIActor->UpdateFpsValue(elapsedTime);
}
}

//----------------------------------------------------------------------------
Expand Down
16 changes: 14 additions & 2 deletions vtkext/private/module/vtkF3DUIActor.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -67,9 +67,21 @@ void vtkF3DUIActor::SetFpsCounterVisibility(bool show)
}

//----------------------------------------------------------------------------
void vtkF3DUIActor::SetFpsValue(int fps)
void vtkF3DUIActor::UpdateFpsValue(const double elapsedFrameTime)
{
this->FpsValue = fps;
this->TotalFrameTimes += elapsedFrameTime;
this->FrameTimes.push_back(elapsedFrameTime);

while (this->TotalFrameTimes > 1.0)
{
double oldestFrameTime = this->FrameTimes.front();

this->FrameTimes.pop_front();
this->TotalFrameTimes -= oldestFrameTime;
}

double averageFrameTime = this->TotalFrameTimes / this->FrameTimes.size();
this->FpsValue = static_cast<int>(std::round(1.0 / averageFrameTime));
}

//----------------------------------------------------------------------------
Expand Down
10 changes: 8 additions & 2 deletions vtkext/private/module/vtkF3DUIActor.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#define vtkF3DUIActor_h

#include <vtkProp.h>
#include <deque>

class vtkOpenGLRenderWindow;

Expand Down Expand Up @@ -81,10 +82,10 @@ class vtkF3DUIActor : public vtkProp
void SetFpsCounterVisibility(bool show);

/**
* Set the fps value
* Updates the fps value
* 0 by default
*/
void SetFpsValue(int fps);
void UpdateFpsValue(const double elapsedFrameTime);

/**
* Set the font file path
Expand Down Expand Up @@ -164,6 +165,11 @@ class vtkF3DUIActor : public vtkProp
bool ConsoleBadgeEnabled = false;

bool FpsCounterVisible = false;

// deque instead of queue to allow for iteration
std::deque<double> FrameTimes;

double TotalFrameTimes = 0.0;
int FpsValue = 0;

std::string FontFile = "";
Expand Down

0 comments on commit b134d54

Please sign in to comment.